
Renames `AuthStruct` to `AuthModel` and `ProductStruct` to `ProductModel` to align with a consistent data model naming convention. Updates all relevant imports, type declarations, and method signatures across the application to reflect these changes, improving codebase clarity and maintainability. Includes minor code style improvements and refactorings in other components.
303 lines
9.6 KiB
Dart
303 lines
9.6 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(
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
ReceptionRoute().go(context);
|
|
},
|
|
title: 'Réceptions',
|
|
isActive: selected.isSelected(menu: 0, sub: 0),
|
|
leadingIcon: Icons.move_to_inbox,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
),
|
|
_ListTile(
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
DeliveryRoute().go(context);
|
|
},
|
|
title: 'Livraisons',
|
|
isActive: selected.isSelected(menu: 0, sub: 1),
|
|
leadingIcon: Icons.local_shipping,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
),
|
|
_ListTile(
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
InventoryRoute().go(context);
|
|
},
|
|
title: 'Inventaires',
|
|
isActive: selected.isSelected(menu: 0, sub: 2),
|
|
leadingIcon: Icons.inventory,
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
),
|
|
],
|
|
),
|
|
|
|
// === 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({
|
|
required this.title,
|
|
this.isActive = false,
|
|
this.onTap,
|
|
this.leadingIcon,
|
|
this.contentPadding,
|
|
this.trailing,
|
|
});
|
|
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(
|
|
selected: isActive,
|
|
selectedTileColor: AppTheme.of(context).primary.withValues(alpha: 0.1),
|
|
onTap: onTap,
|
|
contentPadding: contentPadding,
|
|
leading: Icon(
|
|
leadingIcon,
|
|
color: isActive
|
|
? AppTheme.of(context).primary
|
|
: AppTheme.of(context).primaryText,
|
|
),
|
|
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 Container(
|
|
color: isActive
|
|
? AppTheme.of(context).primary.withValues(alpha: 0.05)
|
|
: null,
|
|
child: 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
|
|
: AppTheme.of(context).primaryText,
|
|
),
|
|
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,
|
|
),
|
|
);
|
|
}
|
|
}
|