
Removes the dedicated `HomePage` and its associated model files. Configures `ReceptionPage` as the new default landing page after successful login and product form submission. Updates navigation and state management dependencies to direct users to the primary operational interface upon entry.
285 lines
8.9 KiB
Dart
285 lines
8.9 KiB
Dart
import 'package:barcode_scanner/backend/schema/user/user_struct.dart';
|
|
import 'package:barcode_scanner/pages/login/login_page_model.dart';
|
|
import 'package:barcode_scanner/pages/operation/reception/reception_page_model.dart';
|
|
import 'package:barcode_scanner/router/go_router_builder.dart';
|
|
import 'package:barcode_scanner/router/go_secure_router_builder.dart';
|
|
import 'package:barcode_scanner/themes/app_theme.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
class DrawerComponent extends ConsumerStatefulWidget {
|
|
const DrawerComponent({
|
|
super.key,
|
|
this.isOperationExpanded = true,
|
|
this.isSettingsExpanded = false,
|
|
this.selectedState = const SelectedDrawerState(
|
|
menuIndex: 0,
|
|
subMenuIndex: 0,
|
|
),
|
|
});
|
|
|
|
final bool isOperationExpanded;
|
|
final bool isSettingsExpanded;
|
|
final SelectedDrawerState selectedState;
|
|
|
|
@override
|
|
ConsumerState<DrawerComponent> createState() => _DrawerComponentState();
|
|
}
|
|
|
|
class _DrawerComponentState extends ConsumerState<DrawerComponent> {
|
|
late bool _isOperationExpanded;
|
|
late bool _isSettingsExpanded;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_isOperationExpanded = widget.isOperationExpanded;
|
|
_isSettingsExpanded = widget.isSettingsExpanded;
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final selected = widget.selectedState;
|
|
|
|
return Drawer(
|
|
backgroundColor: AppTheme.of(context).primaryBackground,
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 16),
|
|
child: Column(
|
|
children: [
|
|
const SizedBox(height: 50),
|
|
|
|
// === Profil utilisateur
|
|
Consumer(
|
|
builder: (context, ref, child) {
|
|
final state = ref.watch(receptionPageModelProvider);
|
|
return ListTile(
|
|
onTap: () => ProfileRoute().push(context),
|
|
contentPadding: EdgeInsets.zero,
|
|
leading: Container(
|
|
width: 60,
|
|
height: 60,
|
|
decoration: BoxDecoration(
|
|
color: AppTheme.of(context).secondaryBackground,
|
|
borderRadius: BorderRadius.circular(60),
|
|
),
|
|
),
|
|
title: Text(
|
|
state.user?.fullName ?? '',
|
|
style: AppTheme.of(context).titleMedium,
|
|
),
|
|
subtitle: Text(
|
|
state.user?.email ?? '',
|
|
style: AppTheme.of(context).bodyMedium,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
|
|
const Divider(),
|
|
|
|
// === Opérations
|
|
_ExpansionTileComponent(
|
|
leadingIcon: Icons.inbox,
|
|
isExpanded: _isOperationExpanded,
|
|
onExpansionChanged: (expanded) =>
|
|
setState(() => _isOperationExpanded = expanded),
|
|
title: 'Opérations',
|
|
isActive: selected.isSelected(menu: 0),
|
|
children: [
|
|
_ListTile(
|
|
title: 'Réceptions',
|
|
isActive: selected.isSelected(menu: 0, sub: 0),
|
|
leadingIcon: Icons.move_to_inbox,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
),
|
|
_ListTile(
|
|
title: 'Livraisons',
|
|
isActive: selected.isSelected(menu: 0, sub: 1),
|
|
leadingIcon: Icons.local_shipping,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
),
|
|
_ListTile(
|
|
title: 'Inventaires',
|
|
isActive: selected.isSelected(menu: 0, sub: 2),
|
|
leadingIcon: Icons.inventory,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
ProductListRoute().push(context);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
|
|
// === Produits
|
|
_ListTile(
|
|
title: "Produits",
|
|
leadingIcon: Icons.insert_chart,
|
|
trailing: const Icon(Icons.keyboard_arrow_right),
|
|
isActive: selected.isSelected(menu: 1),
|
|
contentPadding: const EdgeInsetsDirectional.symmetric(
|
|
horizontal: 10,
|
|
),
|
|
),
|
|
|
|
// === Historique
|
|
_ListTile(
|
|
title: "Historiques",
|
|
leadingIcon: Icons.history,
|
|
trailing: const Icon(Icons.keyboard_arrow_right),
|
|
isActive: selected.isSelected(menu: 2),
|
|
contentPadding: const EdgeInsetsDirectional.symmetric(
|
|
horizontal: 10,
|
|
),
|
|
),
|
|
|
|
// === Paramètres
|
|
_ExpansionTileComponent(
|
|
title: "Paramètres",
|
|
isExpanded: _isSettingsExpanded,
|
|
onExpansionChanged: (expanded) =>
|
|
setState(() => _isSettingsExpanded = expanded),
|
|
isActive: selected.isSelected(menu: 3),
|
|
leadingIcon: Icons.settings,
|
|
children: [
|
|
_ListTile(
|
|
title: 'Connexion Odoo',
|
|
isActive: selected.isSelected(menu: 3, sub: 3),
|
|
leadingIcon: Icons.lock_open,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
),
|
|
_ListTile(
|
|
title: 'Gestion des utilisateurs',
|
|
isActive: selected.isSelected(menu: 3, sub: 4),
|
|
leadingIcon: Icons.group,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
),
|
|
],
|
|
),
|
|
|
|
const Spacer(),
|
|
|
|
// === Déconnexion
|
|
SafeArea(
|
|
child: ListTile(
|
|
onTap: () async {
|
|
await ref.read(loginPageModelProvider.notifier).logOut();
|
|
await UserStruct(id: '1').deleteLocalStorage();
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
SplashRoute().go(context);
|
|
});
|
|
},
|
|
leading: const Icon(Icons.logout),
|
|
title: Text(
|
|
'Se déconnecter',
|
|
style: AppTheme.of(context).bodyLarge,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class SelectedDrawerState {
|
|
const SelectedDrawerState({
|
|
required this.menuIndex,
|
|
required this.subMenuIndex,
|
|
});
|
|
final int menuIndex;
|
|
final int subMenuIndex;
|
|
|
|
bool isSelected({required int menu, int? sub}) {
|
|
if (sub == null) return menuIndex == menu;
|
|
return menuIndex == menu && subMenuIndex == sub;
|
|
}
|
|
}
|
|
|
|
class _ListTile extends StatelessWidget {
|
|
const _ListTile({
|
|
Key? key,
|
|
required this.title,
|
|
this.isActive = false,
|
|
this.onTap,
|
|
this.leadingIcon,
|
|
this.contentPadding,
|
|
this.trailing,
|
|
}) : super(key: key);
|
|
final bool isActive;
|
|
final String title;
|
|
final VoidCallback? onTap;
|
|
final IconData? leadingIcon;
|
|
final EdgeInsetsGeometry? contentPadding;
|
|
final Widget? trailing;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ListTile(
|
|
onTap: onTap,
|
|
contentPadding: contentPadding,
|
|
leading: Icon(
|
|
leadingIcon,
|
|
color: isActive ? AppTheme.of(context).primary : null,
|
|
),
|
|
title: Text(
|
|
title,
|
|
style: AppTheme.of(context).bodyLarge.copyWith(
|
|
color: isActive ? AppTheme.of(context).primary : null,
|
|
),
|
|
),
|
|
trailing: trailing,
|
|
);
|
|
}
|
|
}
|
|
|
|
class _ExpansionTileComponent extends StatelessWidget {
|
|
const _ExpansionTileComponent({
|
|
required this.title,
|
|
this.isExpanded = false,
|
|
this.onExpansionChanged,
|
|
this.isActive = false,
|
|
this.children = const <Widget>[],
|
|
this.leadingIcon,
|
|
});
|
|
final bool isExpanded;
|
|
final void Function(bool)? onExpansionChanged;
|
|
final bool isActive;
|
|
final List<Widget> children;
|
|
final String title;
|
|
final IconData? leadingIcon;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ExpansionTile(
|
|
initiallyExpanded: isExpanded,
|
|
onExpansionChanged: onExpansionChanged,
|
|
tilePadding: const EdgeInsetsDirectional.symmetric(horizontal: 10),
|
|
shape: LinearBorder.none,
|
|
title: Row(
|
|
children: [
|
|
Icon(
|
|
leadingIcon,
|
|
color: isActive ? AppTheme.of(context).primary : null,
|
|
),
|
|
const SizedBox(width: 12),
|
|
Expanded(
|
|
child: Text(
|
|
title,
|
|
style: AppTheme.of(context).bodyLarge.copyWith(
|
|
color: isActive ? AppTheme.of(context).primary : null,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
trailing: Icon(
|
|
isExpanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_right,
|
|
),
|
|
children: children,
|
|
);
|
|
}
|
|
}
|