feat: simplify AdminScreen and refactor ImportScreen to use TabBarView directly
This commit is contained in:
@@ -5,7 +5,14 @@ import 'package:go_router/go_router.dart';
|
|||||||
import '../../features/auth/data/auth_providers.dart';
|
import '../../features/auth/data/auth_providers.dart';
|
||||||
import '../../features/recipes/data/recipes_grid_provider.dart';
|
import '../../features/recipes/data/recipes_grid_provider.dart';
|
||||||
|
|
||||||
const _adminDestination = _AppDestination(
|
const _profileHeaderDestination = _AppDestination(
|
||||||
|
path: '/profile',
|
||||||
|
title: 'Profil',
|
||||||
|
icon: Icons.person,
|
||||||
|
label: 'Profil',
|
||||||
|
);
|
||||||
|
|
||||||
|
const _adminHeaderDestination = _AppDestination(
|
||||||
path: '/admin',
|
path: '/admin',
|
||||||
title: 'Admin',
|
title: 'Admin',
|
||||||
icon: Icons.admin_panel_settings_outlined,
|
icon: Icons.admin_panel_settings_outlined,
|
||||||
@@ -53,24 +60,32 @@ class AppShell extends ConsumerWidget {
|
|||||||
icon: Icons.upload_file_outlined,
|
icon: Icons.upload_file_outlined,
|
||||||
label: 'Importera',
|
label: 'Importera',
|
||||||
),
|
),
|
||||||
_AppDestination(
|
|
||||||
path: '/profile',
|
|
||||||
title: 'Profil',
|
|
||||||
icon: Icons.person,
|
|
||||||
label: 'Profil',
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
List<_AppDestination> _destinations(bool isAdmin) => [
|
List<_AppDestination> _destinations(bool isAdmin) => _baseDestinations;
|
||||||
..._baseDestinations,
|
|
||||||
if (isAdmin) _adminDestination,
|
|
||||||
];
|
|
||||||
|
|
||||||
int _selectedIndex(List<_AppDestination> destinations) {
|
int? _selectedIndex(List<_AppDestination> destinations) {
|
||||||
final index = destinations.indexWhere(
|
final index = destinations.indexWhere(
|
||||||
(destination) => location.startsWith(destination.path),
|
(destination) => location.startsWith(destination.path),
|
||||||
);
|
);
|
||||||
return index < 0 ? 0 : index;
|
return index < 0 ? null : index;
|
||||||
|
}
|
||||||
|
|
||||||
|
_AppDestination _selectedHeaderDestination(
|
||||||
|
List<_AppDestination> destinations,
|
||||||
|
bool isAdmin,
|
||||||
|
) {
|
||||||
|
if (location.startsWith('/profile')) {
|
||||||
|
return _profileHeaderDestination;
|
||||||
|
}
|
||||||
|
if (location.startsWith('/admin') && isAdmin) {
|
||||||
|
return _adminHeaderDestination;
|
||||||
|
}
|
||||||
|
final selectedIndex = _selectedIndex(destinations);
|
||||||
|
if (selectedIndex != null) {
|
||||||
|
return destinations[selectedIndex];
|
||||||
|
}
|
||||||
|
return destinations.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -78,7 +93,7 @@ class AppShell extends ConsumerWidget {
|
|||||||
final isAdmin = ref.watch(isAdminProvider);
|
final isAdmin = ref.watch(isAdminProvider);
|
||||||
final dests = _destinations(isAdmin);
|
final dests = _destinations(isAdmin);
|
||||||
final selectedIndex = _selectedIndex(dests);
|
final selectedIndex = _selectedIndex(dests);
|
||||||
final selectedDestination = dests[selectedIndex];
|
final selectedDestination = _selectedHeaderDestination(dests, isAdmin);
|
||||||
final isWide = MediaQuery.of(context).size.width >= 900;
|
final isWide = MediaQuery.of(context).size.width >= 900;
|
||||||
|
|
||||||
void navigateTo(int index) {
|
void navigateTo(int index) {
|
||||||
@@ -90,6 +105,7 @@ class AppShell extends ConsumerWidget {
|
|||||||
|
|
||||||
final isRecipesRoute = location.startsWith('/recipes') &&
|
final isRecipesRoute = location.startsWith('/recipes') &&
|
||||||
!location.startsWith('/recipes/');
|
!location.startsWith('/recipes/');
|
||||||
|
final isImportRoute = location == '/import';
|
||||||
|
|
||||||
Future<void> logout() async {
|
Future<void> logout() async {
|
||||||
await ref.read(authStateProvider.notifier).logout();
|
await ref.read(authStateProvider.notifier).logout();
|
||||||
@@ -98,9 +114,23 @@ class AppShell extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
Widget shell = Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(selectedDestination.title),
|
title: Text(selectedDestination.title),
|
||||||
|
bottom: isImportRoute
|
||||||
|
? const TabBar(
|
||||||
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
icon: Icon(Icons.restaurant_menu_outlined),
|
||||||
|
text: 'Recept',
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
icon: Icon(Icons.receipt_long_outlined),
|
||||||
|
text: 'Kvitto',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: null,
|
||||||
actions: [
|
actions: [
|
||||||
if (isRecipesRoute)
|
if (isRecipesRoute)
|
||||||
Consumer(
|
Consumer(
|
||||||
@@ -177,7 +207,7 @@ class AppShell extends ConsumerWidget {
|
|||||||
? Row(
|
? Row(
|
||||||
children: [
|
children: [
|
||||||
NavigationRail(
|
NavigationRail(
|
||||||
selectedIndex: selectedIndex,
|
selectedIndex: selectedIndex ?? 0,
|
||||||
onDestinationSelected: navigateTo,
|
onDestinationSelected: navigateTo,
|
||||||
labelType: NavigationRailLabelType.all,
|
labelType: NavigationRailLabelType.all,
|
||||||
destinations: dests
|
destinations: dests
|
||||||
@@ -197,7 +227,7 @@ class AppShell extends ConsumerWidget {
|
|||||||
bottomNavigationBar: isWide
|
bottomNavigationBar: isWide
|
||||||
? null
|
? null
|
||||||
: NavigationBar(
|
: NavigationBar(
|
||||||
selectedIndex: selectedIndex,
|
selectedIndex: selectedIndex ?? 0,
|
||||||
onDestinationSelected: navigateTo,
|
onDestinationSelected: navigateTo,
|
||||||
destinations: dests
|
destinations: dests
|
||||||
.map(
|
.map(
|
||||||
@@ -209,6 +239,12 @@ class AppShell extends ConsumerWidget {
|
|||||||
.toList(),
|
.toList(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (isImportRoute) {
|
||||||
|
shell = DefaultTabController(length: 2, child: shell);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shell;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,7 @@ class AdminScreen extends ConsumerStatefulWidget {
|
|||||||
class _AdminScreenState extends ConsumerState<AdminScreen> {
|
class _AdminScreenState extends ConsumerState<AdminScreen> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return const AdminUsersPanel();
|
||||||
appBar: AppBar(
|
|
||||||
title: const Text('Admin – Användare'),
|
|
||||||
),
|
|
||||||
body: const AdminUsersPanel(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,42 +14,14 @@ class ImportScreen extends StatefulWidget {
|
|||||||
State<ImportScreen> createState() => _ImportScreenState();
|
State<ImportScreen> createState() => _ImportScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ImportScreenState extends State<ImportScreen>
|
class _ImportScreenState extends State<ImportScreen> {
|
||||||
with SingleTickerProviderStateMixin {
|
|
||||||
late final TabController _tabController;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_tabController = TabController(length: 2, vsync: this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_tabController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return const TabBarView(
|
||||||
appBar: AppBar(
|
children: [
|
||||||
title: const Text('Importera'),
|
RecipeImportTab(),
|
||||||
bottom: TabBar(
|
ReceiptImportTab(),
|
||||||
controller: _tabController,
|
],
|
||||||
tabs: const [
|
|
||||||
Tab(icon: Icon(Icons.restaurant_menu_outlined), text: 'Recept'),
|
|
||||||
Tab(icon: Icon(Icons.receipt_long_outlined), text: 'Kvitto'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
body: TabBarView(
|
|
||||||
controller: _tabController,
|
|
||||||
children: const [
|
|
||||||
RecipeImportTab(),
|
|
||||||
ReceiptImportTab(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user