feat: implement API client with JSON handling and error mapping; enhance routing and state management in app shell
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../features/auth/data/auth_providers.dart';
|
||||
|
||||
class AppShell extends ConsumerWidget {
|
||||
final String location;
|
||||
final Widget child;
|
||||
|
||||
const AppShell({
|
||||
super.key,
|
||||
required this.location,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
static const _destinations = [
|
||||
_AppDestination(
|
||||
path: '/recipes',
|
||||
title: 'Recept',
|
||||
icon: Icons.restaurant_menu,
|
||||
label: 'Recept',
|
||||
),
|
||||
_AppDestination(
|
||||
path: '/profile',
|
||||
title: 'Profil',
|
||||
icon: Icons.person,
|
||||
label: 'Profil',
|
||||
),
|
||||
];
|
||||
|
||||
int _selectedIndex() {
|
||||
final index = _destinations.indexWhere(
|
||||
(destination) => location.startsWith(destination.path),
|
||||
);
|
||||
return index < 0 ? 0 : index;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final selectedIndex = _selectedIndex();
|
||||
final selectedDestination = _destinations[selectedIndex];
|
||||
final isWide = MediaQuery.of(context).size.width >= 900;
|
||||
|
||||
Future<void> logout() async {
|
||||
await ref.read(authStateProvider.notifier).logout();
|
||||
if (context.mounted) {
|
||||
context.go('/login');
|
||||
}
|
||||
}
|
||||
|
||||
void navigateTo(int index) {
|
||||
final target = _destinations[index].path;
|
||||
if (target != location && context.mounted) {
|
||||
context.go(target);
|
||||
}
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(selectedDestination.title),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: 'Logga ut',
|
||||
icon: const Icon(Icons.logout),
|
||||
onPressed: logout,
|
||||
),
|
||||
],
|
||||
),
|
||||
body: isWide
|
||||
? Row(
|
||||
children: [
|
||||
NavigationRail(
|
||||
selectedIndex: selectedIndex,
|
||||
onDestinationSelected: navigateTo,
|
||||
labelType: NavigationRailLabelType.all,
|
||||
destinations: _destinations
|
||||
.map(
|
||||
(destination) => NavigationRailDestination(
|
||||
icon: Icon(destination.icon),
|
||||
label: Text(destination.label),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
const VerticalDivider(width: 1),
|
||||
Expanded(child: child),
|
||||
],
|
||||
)
|
||||
: child,
|
||||
bottomNavigationBar: isWide
|
||||
? null
|
||||
: NavigationBar(
|
||||
selectedIndex: selectedIndex,
|
||||
onDestinationSelected: navigateTo,
|
||||
destinations: _destinations
|
||||
.map(
|
||||
(destination) => NavigationDestination(
|
||||
icon: Icon(destination.icon),
|
||||
label: destination.label,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AppDestination {
|
||||
final String path;
|
||||
final String title;
|
||||
final IconData icon;
|
||||
final String label;
|
||||
|
||||
const _AppDestination({
|
||||
required this.path,
|
||||
required this.title,
|
||||
required this.icon,
|
||||
required this.label,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user