barcode_scanner/lib/components/drawer_component.dart
mandreshope 61047f266d chore: Renames project to e_scan
Performs a comprehensive project rename from 'barcode_scanner' to 'e_scan' (or 'eScan' for user-facing labels). This update spans all relevant files, including:

- Application IDs and bundle identifiers for Android, iOS, macOS, and Linux.
- VS Code launch configurations.
- Dart package import paths.
- Project names and titles in `pubspec.yaml`, `README.md`, and platform-specific configurations (e.g., CMakeLists, Info.plist, AndroidManifest).
2025-07-30 09:19:44 +03:00

303 lines
9.5 KiB
Dart

import 'package:e_scan/backend/schema/user/user_struct.dart';
import 'package:e_scan/pages/login/login_page_model.dart';
import 'package:e_scan/pages/operation/reception/reception_page_model.dart';
import 'package:e_scan/router/go_router_builder.dart';
import 'package:e_scan/router/go_secure_router_builder.dart';
import 'package:e_scan/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,
),
);
}
}