440 lines
13 KiB
Dart
440 lines
13 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../../../../shared/widgets/unified_components.dart';
|
|
import '../../../../shared/theme/app_theme.dart';
|
|
import '../../../../core/animations/page_transitions.dart';
|
|
import '../../../demo/presentation/pages/animations_demo_page.dart';
|
|
import '../../../debug/debug_api_test_page.dart';
|
|
|
|
/// Page principale du tableau de bord UnionFlow - Version Unifiée
|
|
///
|
|
/// Utilise l'architecture unifiée avec composants standardisés pour :
|
|
/// - Cohérence visuelle parfaite avec les autres onglets
|
|
/// - Maintenabilité optimale et réutilisabilité maximale
|
|
/// - Performance 60 FPS avec animations fluides
|
|
/// - Expérience utilisateur homogène
|
|
class DashboardPageUnified extends StatelessWidget {
|
|
const DashboardPageUnified({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return UnifiedPageLayout(
|
|
title: 'Tableau de bord',
|
|
subtitle: 'Vue d\'ensemble de votre association',
|
|
icon: Icons.dashboard,
|
|
iconColor: AppTheme.primaryColor,
|
|
actions: _buildActions(context),
|
|
body: Column(
|
|
children: [
|
|
_buildWelcomeSection(),
|
|
const SizedBox(height: AppTheme.spacingLarge),
|
|
_buildKPISection(),
|
|
const SizedBox(height: AppTheme.spacingLarge),
|
|
_buildQuickActionsSection(),
|
|
const SizedBox(height: AppTheme.spacingLarge),
|
|
_buildRecentActivitiesSection(),
|
|
const SizedBox(height: AppTheme.spacingLarge),
|
|
_buildAnalyticsSection(),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Actions de la barre d'outils
|
|
List<Widget> _buildActions(BuildContext context) {
|
|
return [
|
|
IconButton(
|
|
icon: const Icon(Icons.animation),
|
|
onPressed: () => Navigator.of(context).push(
|
|
PageTransitions.morphWithBlur(const AnimationsDemoPage()),
|
|
),
|
|
tooltip: 'Démonstration des animations',
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.notifications_outlined),
|
|
onPressed: () {
|
|
// TODO: Implémenter la navigation vers les notifications
|
|
},
|
|
tooltip: 'Notifications',
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.bug_report),
|
|
onPressed: () => Navigator.of(context).push(
|
|
PageTransitions.slideFromRight(const DebugApiTestPage()),
|
|
),
|
|
tooltip: 'Debug API',
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.settings_outlined),
|
|
onPressed: () {
|
|
// TODO: Implémenter la navigation vers les paramètres
|
|
},
|
|
tooltip: 'Paramètres',
|
|
),
|
|
];
|
|
}
|
|
|
|
/// Section d'accueil personnalisée
|
|
Widget _buildWelcomeSection() {
|
|
return UnifiedCard.elevated(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(AppTheme.spacingLarge),
|
|
child: Row(
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.all(AppTheme.spacingMedium),
|
|
decoration: BoxDecoration(
|
|
color: AppTheme.primaryColor.withOpacity(0.1),
|
|
borderRadius: BorderRadius.circular(AppTheme.borderRadiusMedium),
|
|
),
|
|
child: Icon(
|
|
Icons.waving_hand,
|
|
color: AppTheme.primaryColor,
|
|
size: 32,
|
|
),
|
|
),
|
|
const SizedBox(width: AppTheme.spacingMedium),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'Bonjour !',
|
|
style: AppTheme.headlineSmall.copyWith(
|
|
color: AppTheme.primaryColor,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
const SizedBox(height: AppTheme.spacingXSmall),
|
|
Text(
|
|
'Bienvenue sur votre tableau de bord UnionFlow',
|
|
style: AppTheme.bodyMedium.copyWith(
|
|
color: AppTheme.textSecondary,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Section des indicateurs clés de performance
|
|
Widget _buildKPISection() {
|
|
final kpis = [
|
|
UnifiedKPIData(
|
|
title: 'Membres',
|
|
value: '247',
|
|
icon: Icons.people,
|
|
color: AppTheme.primaryColor,
|
|
trend: UnifiedKPITrend(
|
|
direction: UnifiedKPITrendDirection.up,
|
|
value: '+12',
|
|
label: 'ce mois',
|
|
),
|
|
),
|
|
UnifiedKPIData(
|
|
title: 'Événements',
|
|
value: '18',
|
|
icon: Icons.event,
|
|
color: AppTheme.accentColor,
|
|
trend: UnifiedKPITrend(
|
|
direction: UnifiedKPITrendDirection.up,
|
|
value: '+3',
|
|
label: 'ce mois',
|
|
),
|
|
),
|
|
UnifiedKPIData(
|
|
title: 'Cotisations',
|
|
value: '89%',
|
|
icon: Icons.account_balance_wallet,
|
|
color: AppTheme.successColor,
|
|
trend: UnifiedKPITrend(
|
|
direction: UnifiedKPITrendDirection.up,
|
|
value: '+5%',
|
|
label: 'vs mois dernier',
|
|
),
|
|
),
|
|
UnifiedKPIData(
|
|
title: 'Trésorerie',
|
|
value: '12.5K€',
|
|
icon: Icons.euro,
|
|
color: AppTheme.warningColor,
|
|
trend: UnifiedKPITrend(
|
|
direction: UnifiedKPITrendDirection.stable,
|
|
value: '0%',
|
|
label: 'stable',
|
|
),
|
|
),
|
|
];
|
|
|
|
return UnifiedKPISection(
|
|
title: 'Vue d\'ensemble',
|
|
kpis: kpis,
|
|
);
|
|
}
|
|
|
|
/// Section des actions rapides
|
|
Widget _buildQuickActionsSection() {
|
|
final actions = [
|
|
UnifiedQuickAction(
|
|
id: 'add_member',
|
|
title: 'Nouveau\nMembre',
|
|
icon: Icons.person_add,
|
|
color: AppTheme.primaryColor,
|
|
),
|
|
UnifiedQuickAction(
|
|
id: 'add_event',
|
|
title: 'Nouvel\nÉvénement',
|
|
icon: Icons.event_available,
|
|
color: AppTheme.accentColor,
|
|
badgeCount: 3,
|
|
),
|
|
UnifiedQuickAction(
|
|
id: 'manage_cotisations',
|
|
title: 'Gérer\nCotisations',
|
|
icon: Icons.account_balance_wallet,
|
|
color: AppTheme.successColor,
|
|
badgeCount: 7,
|
|
),
|
|
UnifiedQuickAction(
|
|
id: 'reports',
|
|
title: 'Rapports\n& Stats',
|
|
icon: Icons.analytics,
|
|
color: AppTheme.infoColor,
|
|
),
|
|
UnifiedQuickAction(
|
|
id: 'communications',
|
|
title: 'Envoyer\nMessage',
|
|
icon: Icons.send,
|
|
color: AppTheme.warningColor,
|
|
),
|
|
UnifiedQuickAction(
|
|
id: 'settings',
|
|
title: 'Paramètres\nAssociation',
|
|
icon: Icons.settings,
|
|
color: AppTheme.textSecondary,
|
|
),
|
|
];
|
|
|
|
return UnifiedQuickActionsSection(
|
|
title: 'Actions rapides',
|
|
actions: actions,
|
|
onActionTap: _handleQuickAction,
|
|
);
|
|
}
|
|
|
|
/// Section des activités récentes
|
|
Widget _buildRecentActivitiesSection() {
|
|
final activities = [
|
|
_ActivityItem(
|
|
title: 'Nouveau membre inscrit',
|
|
subtitle: 'Marie Dubois a rejoint l\'association',
|
|
icon: Icons.person_add,
|
|
color: AppTheme.successColor,
|
|
time: 'Il y a 2h',
|
|
),
|
|
_ActivityItem(
|
|
title: 'Événement créé',
|
|
subtitle: 'Assemblée Générale 2024 programmée',
|
|
icon: Icons.event,
|
|
color: AppTheme.accentColor,
|
|
time: 'Il y a 4h',
|
|
),
|
|
_ActivityItem(
|
|
title: 'Cotisation reçue',
|
|
subtitle: 'Jean Martin - Cotisation annuelle',
|
|
icon: Icons.payment,
|
|
color: AppTheme.primaryColor,
|
|
time: 'Il y a 6h',
|
|
),
|
|
];
|
|
|
|
return UnifiedCard.elevated(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(AppTheme.spacingLarge),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(
|
|
Icons.timeline,
|
|
color: AppTheme.primaryColor,
|
|
size: 24,
|
|
),
|
|
const SizedBox(width: AppTheme.spacingSmall),
|
|
Text(
|
|
'Activités récentes',
|
|
style: AppTheme.titleMedium.copyWith(
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: AppTheme.spacingMedium),
|
|
...activities.map((activity) => _buildActivityItem(activity)),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Section d'analyses et graphiques
|
|
Widget _buildAnalyticsSection() {
|
|
return UnifiedCard.elevated(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(AppTheme.spacingLarge),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(
|
|
Icons.analytics,
|
|
color: AppTheme.accentColor,
|
|
size: 24,
|
|
),
|
|
const SizedBox(width: AppTheme.spacingSmall),
|
|
Text(
|
|
'Analyses & Tendances',
|
|
style: AppTheme.titleMedium.copyWith(
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
const Spacer(),
|
|
UnifiedButton.tertiary(
|
|
text: 'Voir plus',
|
|
size: UnifiedButtonSize.small,
|
|
onPressed: () {
|
|
// TODO: Navigation vers analyses détaillées
|
|
},
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(height: AppTheme.spacingMedium),
|
|
Container(
|
|
height: 120,
|
|
decoration: BoxDecoration(
|
|
color: AppTheme.accentColor.withOpacity(0.1),
|
|
borderRadius: BorderRadius.circular(AppTheme.borderRadiusMedium),
|
|
),
|
|
child: Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
Icons.bar_chart,
|
|
color: AppTheme.accentColor,
|
|
size: 48,
|
|
),
|
|
const SizedBox(height: AppTheme.spacingSmall),
|
|
Text(
|
|
'Graphiques interactifs',
|
|
style: AppTheme.bodyMedium.copyWith(
|
|
color: AppTheme.textSecondary,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Construit un élément d'activité
|
|
Widget _buildActivityItem(_ActivityItem activity) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: AppTheme.spacingSmall),
|
|
child: Row(
|
|
children: [
|
|
Container(
|
|
padding: const EdgeInsets.all(AppTheme.spacingSmall),
|
|
decoration: BoxDecoration(
|
|
color: activity.color.withOpacity(0.1),
|
|
borderRadius: BorderRadius.circular(AppTheme.borderRadiusSmall),
|
|
),
|
|
child: Icon(
|
|
activity.icon,
|
|
color: activity.color,
|
|
size: 16,
|
|
),
|
|
),
|
|
const SizedBox(width: AppTheme.spacingMedium),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
activity.title,
|
|
style: AppTheme.bodyMedium.copyWith(
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
Text(
|
|
activity.subtitle,
|
|
style: AppTheme.bodySmall.copyWith(
|
|
color: AppTheme.textSecondary,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Text(
|
|
activity.time,
|
|
style: AppTheme.bodySmall.copyWith(
|
|
color: AppTheme.textSecondary,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Gère les actions rapides
|
|
void _handleQuickAction(UnifiedQuickAction action) {
|
|
// TODO: Implémenter la navigation selon l'action
|
|
switch (action.id) {
|
|
case 'add_member':
|
|
// Navigation vers ajout membre
|
|
break;
|
|
case 'add_event':
|
|
// Navigation vers ajout événement
|
|
break;
|
|
case 'manage_cotisations':
|
|
// Navigation vers gestion cotisations
|
|
break;
|
|
case 'reports':
|
|
// Navigation vers rapports
|
|
break;
|
|
case 'communications':
|
|
// Navigation vers communications
|
|
break;
|
|
case 'settings':
|
|
// Navigation vers paramètres
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Modèle pour les éléments d'activité
|
|
class _ActivityItem {
|
|
final String title;
|
|
final String subtitle;
|
|
final IconData icon;
|
|
final Color color;
|
|
final String time;
|
|
|
|
const _ActivityItem({
|
|
required this.title,
|
|
required this.subtitle,
|
|
required this.icon,
|
|
required this.color,
|
|
required this.time,
|
|
});
|
|
}
|