417 lines
14 KiB
Dart
417 lines
14 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../../../../../shared/design_system/unionflow_design_system.dart';
|
|
import '../../pages/connected_dashboard_page.dart';
|
|
import '../../pages/advanced_dashboard_page.dart';
|
|
import '../../../../settings/presentation/pages/language_settings_page.dart';
|
|
import '../../../../settings/presentation/pages/system_settings_page.dart';
|
|
import '../../../../reports/presentation/pages/reports_page_wrapper.dart';
|
|
import '../../../../members/presentation/pages/members_page_wrapper.dart';
|
|
import '../../../../events/presentation/pages/events_page_wrapper.dart';
|
|
import '../../../../contributions/presentation/pages/contributions_page_wrapper.dart';
|
|
|
|
/// Widget de navigation pour les différents types de dashboard
|
|
class DashboardNavigation extends StatefulWidget {
|
|
final String organizationId;
|
|
final String userId;
|
|
|
|
const DashboardNavigation({
|
|
super.key,
|
|
required this.organizationId,
|
|
required this.userId,
|
|
});
|
|
|
|
@override
|
|
State<DashboardNavigation> createState() => _DashboardNavigationState();
|
|
}
|
|
|
|
class _DashboardNavigationState extends State<DashboardNavigation> {
|
|
int _currentIndex = 0;
|
|
|
|
final List<DashboardTab> _tabs = [
|
|
const DashboardTab(
|
|
title: 'Accueil',
|
|
icon: Icons.home,
|
|
activeIcon: Icons.home,
|
|
type: DashboardType.home,
|
|
),
|
|
const DashboardTab(
|
|
title: 'Analytics',
|
|
icon: Icons.analytics_outlined,
|
|
activeIcon: Icons.analytics,
|
|
type: DashboardType.analytics,
|
|
),
|
|
const DashboardTab(
|
|
title: 'Rapports',
|
|
icon: Icons.assessment_outlined,
|
|
activeIcon: Icons.assessment,
|
|
type: DashboardType.reports,
|
|
),
|
|
const DashboardTab(
|
|
title: 'Paramètres',
|
|
icon: Icons.settings_outlined,
|
|
activeIcon: Icons.settings,
|
|
type: DashboardType.settings,
|
|
),
|
|
];
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: _buildCurrentPage(),
|
|
bottomNavigationBar: _buildBottomNavigationBar(),
|
|
floatingActionButton: _buildFloatingActionButton(),
|
|
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
|
|
);
|
|
}
|
|
|
|
Widget _buildCurrentPage() {
|
|
switch (_tabs[_currentIndex].type) {
|
|
case DashboardType.home:
|
|
return ConnectedDashboardPage(
|
|
organizationId: widget.organizationId,
|
|
userId: widget.userId,
|
|
);
|
|
case DashboardType.analytics:
|
|
return AdvancedDashboardPage(
|
|
organizationId: widget.organizationId,
|
|
userId: widget.userId,
|
|
);
|
|
case DashboardType.reports:
|
|
return _buildReportsPage();
|
|
case DashboardType.settings:
|
|
return _buildSettingsPage();
|
|
}
|
|
}
|
|
|
|
Widget _buildBottomNavigationBar() {
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).cardColor,
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.05),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, -2),
|
|
),
|
|
],
|
|
),
|
|
child: BottomAppBar(
|
|
shape: const CircularNotchedRectangle(),
|
|
notchMargin: 8,
|
|
color: Theme.of(context).cardColor,
|
|
elevation: 0,
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
children: _tabs.asMap().entries.map((entry) {
|
|
final index = entry.key;
|
|
final tab = entry.value;
|
|
final isActive = index == _currentIndex;
|
|
|
|
// Skip the middle item for FAB space
|
|
if (index == 2) {
|
|
return const SizedBox(width: 40);
|
|
}
|
|
|
|
return _buildNavItem(tab, isActive, index);
|
|
}).toList(),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildNavItem(DashboardTab tab, bool isActive, int index) {
|
|
return GestureDetector(
|
|
onTap: () => setState(() => _currentIndex = index),
|
|
child: Container(
|
|
padding: const EdgeInsets.symmetric(
|
|
vertical: 8,
|
|
horizontal: 16,
|
|
),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(
|
|
isActive ? tab.activeIcon : tab.icon,
|
|
color: isActive ? AppColors.primaryGreen : AppColors.textSecondaryLight,
|
|
size: 20,
|
|
),
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
tab.title,
|
|
style: AppTypography.badgeText.copyWith(
|
|
color: isActive ? AppColors.primaryGreen : AppColors.textSecondaryLight,
|
|
fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
|
|
fontSize: 9,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildFloatingActionButton() {
|
|
return FloatingActionButton(
|
|
onPressed: _showQuickActions,
|
|
backgroundColor: AppColors.primaryGreen,
|
|
elevation: 4,
|
|
child: const Icon(
|
|
Icons.add_outlined,
|
|
color: Colors.white,
|
|
size: 28,
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildReportsPage() {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text('Rapports'.toUpperCase(), style: AppTypography.subtitleSmall.copyWith(fontWeight: FontWeight.bold, color: Colors.white, letterSpacing: 1.1)),
|
|
backgroundColor: AppColors.primaryGreen,
|
|
foregroundColor: Colors.white,
|
|
automaticallyImplyLeading: false,
|
|
),
|
|
body: Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
const Icon(
|
|
Icons.assessment_outlined,
|
|
size: 48,
|
|
color: AppColors.textSecondaryLight,
|
|
),
|
|
const SizedBox(height: 16),
|
|
Text(
|
|
'Page Rapports'.toUpperCase(),
|
|
style: AppTypography.subtitleSmall.copyWith(fontWeight: FontWeight.bold),
|
|
),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
'En cours de développement',
|
|
style: AppTypography.bodyTextSmall.copyWith(
|
|
color: AppColors.textSecondaryLight,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSettingsPage() {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text('Paramètres'.toUpperCase(), style: AppTypography.subtitleSmall.copyWith(fontWeight: FontWeight.bold, color: Colors.white, letterSpacing: 1.1)),
|
|
backgroundColor: AppColors.primaryGreen,
|
|
foregroundColor: Colors.white,
|
|
automaticallyImplyLeading: false,
|
|
),
|
|
body: ListView(
|
|
padding: const EdgeInsets.all(16),
|
|
children: [
|
|
_buildSettingsSection(
|
|
'Apparence',
|
|
[
|
|
_buildSettingsTile(
|
|
'Thème',
|
|
'Design System UnionFlow',
|
|
Icons.palette_outlined,
|
|
() => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const SystemSettingsPage())),
|
|
),
|
|
_buildSettingsTile(
|
|
'Langue',
|
|
'Français',
|
|
Icons.language_outlined,
|
|
() => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const LanguageSettingsPage())),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 24),
|
|
_buildSettingsSection(
|
|
'Notifications',
|
|
[
|
|
_buildSettingsTile(
|
|
'Notifications push',
|
|
'Activées',
|
|
Icons.notifications_outlined,
|
|
() => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const SystemSettingsPage())),
|
|
),
|
|
_buildSettingsTile(
|
|
'Emails',
|
|
'Quotidien',
|
|
Icons.email_outlined,
|
|
() => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const SystemSettingsPage())),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: 24),
|
|
_buildSettingsSection(
|
|
'Données',
|
|
[
|
|
_buildSettingsTile(
|
|
'Synchronisation',
|
|
'Automatique',
|
|
Icons.sync_outlined,
|
|
() => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const SystemSettingsPage())),
|
|
),
|
|
_buildSettingsTile(
|
|
'Cache',
|
|
'Vider le cache',
|
|
Icons.storage_outlined,
|
|
() => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const SystemSettingsPage())),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSettingsSection(String title, List<Widget> children) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
title.toUpperCase(),
|
|
style: AppTypography.subtitleSmall.copyWith(fontWeight: FontWeight.bold, color: AppColors.primaryGreen, fontSize: 10),
|
|
),
|
|
const SizedBox(height: 12),
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).cardColor,
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: AppColors.lightBorder),
|
|
),
|
|
child: Column(children: children),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildSettingsTile(
|
|
String title,
|
|
String subtitle,
|
|
IconData icon,
|
|
VoidCallback onTap,
|
|
) {
|
|
return ListTile(
|
|
leading: Icon(icon, color: AppColors.primaryGreen, size: 20),
|
|
title: Text(title, style: AppTypography.actionText.copyWith(fontSize: 13)),
|
|
subtitle: Text(subtitle, style: AppTypography.subtitleSmall.copyWith(fontSize: 10)),
|
|
trailing: const Icon(
|
|
Icons.chevron_right_outlined,
|
|
color: AppColors.textSecondaryLight,
|
|
size: 16,
|
|
),
|
|
onTap: onTap,
|
|
);
|
|
}
|
|
|
|
void _showQuickActions() {
|
|
showModalBottomSheet(
|
|
context: context,
|
|
backgroundColor: Colors.transparent,
|
|
builder: (context) => Container(
|
|
decoration: BoxDecoration(
|
|
color: Theme.of(context).cardColor,
|
|
borderRadius: const BorderRadius.only(
|
|
topLeft: Radius.circular(16),
|
|
topRight: Radius.circular(16),
|
|
),
|
|
),
|
|
padding: const EdgeInsets.all(20),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Container(
|
|
width: 40,
|
|
height: 4,
|
|
decoration: BoxDecoration(
|
|
color: AppColors.lightBorder,
|
|
borderRadius: BorderRadius.circular(2),
|
|
),
|
|
),
|
|
const SizedBox(height: 20),
|
|
Text(
|
|
'ACTIONS RAPIDES',
|
|
style: AppTypography.subtitleSmall.copyWith(fontWeight: FontWeight.bold, letterSpacing: 1.1),
|
|
),
|
|
const SizedBox(height: 20),
|
|
GridView.count(
|
|
crossAxisCount: 3,
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
crossAxisSpacing: 12,
|
|
mainAxisSpacing: 12,
|
|
children: [
|
|
_buildQuickActionItem(context, 'Nouveau\nMembre', Icons.person_add_outlined, AppColors.success, () => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const MembersPageWrapper()))),
|
|
_buildQuickActionItem(context, 'Créer\nÉvénement', Icons.event_available_outlined, AppColors.primaryGreen, () => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const EventsPageWrapper()))),
|
|
_buildQuickActionItem(context, 'Ajouter\nContribution', Icons.account_balance_wallet_outlined, AppColors.brandGreen, () => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const ContributionsPageWrapper()))),
|
|
_buildQuickActionItem(context, 'Générer\nRapport', Icons.assessment_outlined, AppColors.info, () => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const ReportsPageWrapper()))),
|
|
_buildQuickActionItem(context, 'Paramètres', Icons.settings_outlined, AppColors.textSecondaryLight, () => Navigator.of(context).push(MaterialPageRoute<void>(builder: (_) => const SystemSettingsPage()))),
|
|
],
|
|
),
|
|
const SizedBox(height: 20),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildQuickActionItem(BuildContext context, String title, IconData icon, Color color, VoidCallback onNavigate) {
|
|
return GestureDetector(
|
|
onTap: () {
|
|
Navigator.pop(context);
|
|
onNavigate();
|
|
},
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
color: color.withOpacity(0.1),
|
|
borderRadius: BorderRadius.circular(12),
|
|
),
|
|
padding: const EdgeInsets.all(12),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(icon, color: color, size: 20),
|
|
const SizedBox(height: 8),
|
|
Text(
|
|
title,
|
|
style: AppTypography.subtitleSmall.copyWith(
|
|
color: AppColors.textPrimaryLight,
|
|
fontSize: 9,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class DashboardTab {
|
|
final String title;
|
|
final IconData icon;
|
|
final IconData activeIcon;
|
|
final DashboardType type;
|
|
|
|
const DashboardTab({
|
|
required this.title,
|
|
required this.icon,
|
|
required this.activeIcon,
|
|
required this.type,
|
|
});
|
|
}
|
|
|
|
enum DashboardType {
|
|
home,
|
|
analytics,
|
|
reports,
|
|
settings,
|
|
}
|