
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).
303 lines
9.5 KiB
Dart
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,
|
|
),
|
|
);
|
|
}
|
|
}
|