
- Extracts the complex `Drawer` widget from the `HomePage` into a dedicated `DrawerComponent`. This enhances modularity, improves code readability, and allows for easier reuse of the navigation drawer across the application. - Updates iOS project configuration files (`project.pbxproj` and `contents.xcworkspacedata`) to properly integrate CocoaPods dependencies. This typically occurs after running `pod install` and includes adding Pods frameworks, build phases, and xcconfig references. - Updates the Flutter SDK path in VS Code settings to a newer version.
270 lines
8.6 KiB
Dart
270 lines
8.6 KiB
Dart
import 'package:barcode_scanner/backend/schema/user/user_struct.dart';
|
|
import 'package:barcode_scanner/pages/home_page/home_page_model.dart';
|
|
import 'package:barcode_scanner/pages/login_page/login_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.selectedMenuIndex = 0,
|
|
this.selectedSubMenuIndex = 0,
|
|
});
|
|
final bool isOperationExpanded;
|
|
final bool isSettingsExpanded;
|
|
final int selectedMenuIndex;
|
|
final int selectedSubMenuIndex;
|
|
|
|
@override
|
|
ConsumerState<DrawerComponent> createState() => _DrawerComponentState();
|
|
}
|
|
|
|
class _DrawerComponentState extends ConsumerState<DrawerComponent> {
|
|
bool _isOperationExpanded = false;
|
|
bool _isSettingsExpanded = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
_isOperationExpanded = widget.isOperationExpanded;
|
|
_isSettingsExpanded = widget.isSettingsExpanded;
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
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(homePageModelProvider);
|
|
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(),
|
|
|
|
// === ExpansionTile Opérations
|
|
_ExpansionTileComponent(
|
|
leadingIcon: Icons.inbox,
|
|
isExpanded: _isOperationExpanded,
|
|
onExpansionChanged: (expanded) {
|
|
setState(() => _isOperationExpanded = expanded);
|
|
},
|
|
title: 'Opérations',
|
|
isActive: widget.selectedMenuIndex == 0,
|
|
children: [
|
|
_ListTile(
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
leadingIcon: Icons.move_to_inbox,
|
|
isActive: widget.selectedSubMenuIndex == 0,
|
|
title: 'Réceptions',
|
|
),
|
|
_ListTile(
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
leadingIcon: Icons.local_shipping,
|
|
title: 'Livraisons',
|
|
isActive: widget.selectedSubMenuIndex == 1,
|
|
),
|
|
_ListTile(
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
ProductListRoute().push(context);
|
|
},
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
leadingIcon: Icons.inventory,
|
|
title: 'Inventaires',
|
|
isActive: widget.selectedSubMenuIndex == 2,
|
|
),
|
|
],
|
|
),
|
|
|
|
// === Produits
|
|
_ListTile(
|
|
contentPadding: const EdgeInsetsDirectional.symmetric(
|
|
horizontal: 10,
|
|
),
|
|
leadingIcon: Icons.insert_chart,
|
|
title: "Produits",
|
|
isActive: widget.selectedMenuIndex == 1,
|
|
trailing: const Icon(Icons.keyboard_arrow_right),
|
|
),
|
|
|
|
// === Historique
|
|
_ListTile(
|
|
contentPadding: const EdgeInsetsDirectional.symmetric(
|
|
horizontal: 10,
|
|
),
|
|
leadingIcon: Icons.history,
|
|
title: "Historiques",
|
|
trailing: const Icon(Icons.keyboard_arrow_right),
|
|
isActive: widget.selectedMenuIndex == 2,
|
|
),
|
|
|
|
// === ExpansionTile Paramètres
|
|
_ExpansionTileComponent(
|
|
isActive: widget.selectedMenuIndex == 3,
|
|
isExpanded: _isSettingsExpanded,
|
|
onExpansionChanged: (expanded) {
|
|
setState(() => _isSettingsExpanded = expanded);
|
|
},
|
|
leadingIcon: Icons.settings,
|
|
title: "Paramètres",
|
|
children: [
|
|
_ListTile(
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
leadingIcon: Icons.lock_open,
|
|
title: 'Connexion Odoo',
|
|
isActive: widget.selectedSubMenuIndex == 3,
|
|
),
|
|
_ListTile(
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 40),
|
|
leadingIcon: Icons.group,
|
|
title: 'Gestion des utilisateurs',
|
|
isActive: widget.selectedSubMenuIndex == 4,
|
|
),
|
|
],
|
|
),
|
|
|
|
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 _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,
|
|
);
|
|
}
|
|
}
|