feat: Refactor routing and navigation structure with StatefulShellRoute
Test Suite / test (24.15.0) (push) Has been cancelled

- Introduced a new function `_shellBranchIndexForPath` to determine the index of the shell branch based on the path.
- Replaced `ShellRoute` with `StatefulShellRoute.indexedStack` for better state management during navigation.
- Updated `AppShell` to handle navigation path changes and integrate with the new routing structure.
- Organized routes into `StatefulShellBranch` for better modularity and clarity.
- Enhanced admin panel functionality with improved alias management and UI updates.
- Added new methods in `ReceiptImportSessionNotifier` for managing selected items and edits more efficiently.
- Improved UI components in receipt import and admin panels for better performance and user experience.
- Added PageStorageKeys to various ListViews to maintain scroll positions across navigation.
- Documented performance goals and profiling strategies in a new PERFORMANCE.md file.
This commit is contained in:
Nils-Johan Gynther
2026-05-08 12:51:38 +02:00
parent 73309cb110
commit 0873fa42bb
12 changed files with 625 additions and 285 deletions
@@ -166,6 +166,49 @@ class _AdminAliasesPanelState extends ConsumerState<AdminAliasesPanel> {
alias.displayProductName.toLowerCase().contains(query);
}).toList();
Widget buildAliasCard(ReceiptAlias alias) {
return Card(
child: ListTile(
leading: const Icon(Icons.link_outlined),
title: Text(alias.receiptName, style: const TextStyle(fontWeight: FontWeight.w500)),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'${alias.displayProductName}',
style: const TextStyle(fontWeight: FontWeight.w400),
),
Text(
'Produkt-ID: ${alias.productId}',
style: TextStyle(
fontSize: 11,
color: Theme.of(context).colorScheme.outline,
),
),
],
),
trailing: IconButton(
onPressed: () => _removeAlias(alias),
icon: const Icon(Icons.delete_outline),
tooltip: 'Ta bort alias',
color: Theme.of(context).colorScheme.error,
),
),
);
}
Widget buildAliasList({EdgeInsetsGeometry padding = EdgeInsets.zero}) {
return ListView.builder(
padding: padding,
itemCount: filteredAliases.length,
itemBuilder: (context, index) {
final alias = filteredAliases[index];
return buildAliasCard(alias);
},
);
}
final content = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -230,51 +273,37 @@ class _AdminAliasesPanelState extends ConsumerState<AdminAliasesPanel> {
onChanged: (value) => setState(() => _search = value),
),
const SizedBox(height: 12),
if (filteredAliases.isEmpty)
const Text('Inga alias hittades.')
else
...filteredAliases.map(
(alias) => Card(
child: ListTile(
leading: const Icon(Icons.link_outlined),
title: Text(alias.receiptName, style: const TextStyle(fontWeight: FontWeight.w500)),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'${alias.displayProductName}',
style: const TextStyle(fontWeight: FontWeight.w400),
),
Text(
'Produkt-ID: ${alias.productId}',
style: TextStyle(
fontSize: 11,
color: Theme.of(context).colorScheme.outline,
),
),
],
),
trailing: IconButton(
onPressed: () => _removeAlias(alias),
icon: const Icon(Icons.delete_outline),
tooltip: 'Ta bort alias',
color: Theme.of(context).colorScheme.error,
),
),
),
),
if (filteredAliases.isEmpty) const Text('Inga alias hittades.'),
],
);
if (!widget.embedded) {
if (filteredAliases.isEmpty) {
return ListView(
padding: const EdgeInsets.all(16),
children: [content],
);
}
return ListView(
padding: const EdgeInsets.all(16),
children: [content],
children: [
content,
const SizedBox(height: 8),
...filteredAliases.map(buildAliasCard),
],
);
}
return content;
if (filteredAliases.isEmpty) return content;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
content,
const SizedBox(height: 8),
Expanded(child: buildAliasList()),
],
);
}
}