320 lines
7.9 KiB
Dart
320 lines
7.9 KiB
Dart
library dashboard_widgets;
|
|
|
|
/// Exports pour tous les widgets du dashboard UnionFlow
|
|
///
|
|
/// Ce fichier centralise tous les imports des composants du dashboard
|
|
/// pour faciliter leur utilisation dans les pages et autres widgets.
|
|
|
|
// Widgets communs réutilisables
|
|
export 'common/stat_card.dart';
|
|
export 'common/section_header.dart';
|
|
export 'common/activity_item.dart';
|
|
|
|
// Sections principales du dashboard
|
|
export 'dashboard_header.dart';
|
|
export 'quick_stats_section.dart';
|
|
export 'recent_activities_section.dart';
|
|
export 'upcoming_events_section.dart';
|
|
|
|
// Composants spécialisés
|
|
export 'components/cards/performance_card.dart';
|
|
|
|
// Widgets existants (legacy) - gardés pour compatibilité
|
|
import 'package:flutter/material.dart';
|
|
import '../../../../core/design_system/tokens/tokens.dart';
|
|
|
|
/// Widget pour afficher une grille d'actions rapides
|
|
class DashboardQuickActionsGrid extends StatelessWidget {
|
|
final List<Widget> children;
|
|
final int crossAxisCount;
|
|
|
|
const DashboardQuickActionsGrid({
|
|
super.key,
|
|
required this.children,
|
|
this.crossAxisCount = 2,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return GridView.count(
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
crossAxisCount: crossAxisCount,
|
|
childAspectRatio: 1.2,
|
|
crossAxisSpacing: SpacingTokens.md,
|
|
mainAxisSpacing: SpacingTokens.md,
|
|
children: children,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Widget pour une action rapide
|
|
class DashboardQuickAction extends StatelessWidget {
|
|
final String title;
|
|
final IconData icon;
|
|
final Color? color;
|
|
final VoidCallback? onTap;
|
|
|
|
const DashboardQuickAction({
|
|
super.key,
|
|
required this.title,
|
|
required this.icon,
|
|
this.color,
|
|
this.onTap,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Card(
|
|
elevation: 2,
|
|
child: InkWell(
|
|
onTap: onTap,
|
|
borderRadius: BorderRadius.circular(RadiusTokens.md),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(SpacingTokens.lg),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
icon,
|
|
size: 32,
|
|
color: color ?? ColorTokens.primary,
|
|
),
|
|
const SizedBox(height: SpacingTokens.sm),
|
|
Text(
|
|
title,
|
|
style: TypographyTokens.bodyMedium,
|
|
textAlign: TextAlign.center,
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Widget pour afficher une section d'activité récente
|
|
class DashboardRecentActivitySection extends StatelessWidget {
|
|
final List<Widget> children;
|
|
final String title;
|
|
|
|
const DashboardRecentActivitySection({
|
|
super.key,
|
|
required this.children,
|
|
this.title = 'Activité Récente',
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
title,
|
|
style: TypographyTokens.headlineSmall,
|
|
),
|
|
const SizedBox(height: SpacingTokens.md),
|
|
...children,
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Widget pour une activité
|
|
class DashboardActivity extends StatelessWidget {
|
|
final String title;
|
|
final String subtitle;
|
|
final IconData icon;
|
|
final Color? color;
|
|
|
|
const DashboardActivity({
|
|
super.key,
|
|
required this.title,
|
|
required this.subtitle,
|
|
required this.icon,
|
|
this.color,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Card(
|
|
margin: const EdgeInsets.only(bottom: SpacingTokens.sm),
|
|
child: ListTile(
|
|
leading: CircleAvatar(
|
|
backgroundColor: color ?? ColorTokens.primary,
|
|
child: Icon(icon, color: Colors.white),
|
|
),
|
|
title: Text(title),
|
|
subtitle: Text(subtitle),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Widget pour une section d'insights
|
|
class DashboardInsightsSection extends StatelessWidget {
|
|
final List<Widget> children;
|
|
|
|
const DashboardInsightsSection({
|
|
super.key,
|
|
required this.children,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
const Text(
|
|
'Insights',
|
|
style: TypographyTokens.headlineSmall,
|
|
),
|
|
const SizedBox(height: SpacingTokens.md),
|
|
...children,
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Widget pour une statistique
|
|
class DashboardStat extends StatelessWidget {
|
|
final String title;
|
|
final String value;
|
|
final IconData icon;
|
|
final Color? color;
|
|
final VoidCallback? onTap;
|
|
|
|
const DashboardStat({
|
|
super.key,
|
|
required this.title,
|
|
required this.value,
|
|
required this.icon,
|
|
this.color,
|
|
this.onTap,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Card(
|
|
elevation: 2,
|
|
child: InkWell(
|
|
onTap: onTap,
|
|
borderRadius: BorderRadius.circular(RadiusTokens.md),
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(SpacingTokens.lg),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Icon(
|
|
icon,
|
|
size: 32,
|
|
color: color ?? ColorTokens.primary,
|
|
),
|
|
const SizedBox(height: SpacingTokens.sm),
|
|
Text(
|
|
value,
|
|
style: TypographyTokens.headlineSmall.copyWith(
|
|
fontWeight: FontWeight.bold,
|
|
color: color ?? ColorTokens.primary,
|
|
),
|
|
),
|
|
const SizedBox(height: SpacingTokens.xs),
|
|
Text(
|
|
title,
|
|
style: TypographyTokens.bodySmall,
|
|
textAlign: TextAlign.center,
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Widget pour la grille de statistiques
|
|
class DashboardStatsGrid extends StatelessWidget {
|
|
final List<Widget> children;
|
|
final int crossAxisCount;
|
|
|
|
const DashboardStatsGrid({
|
|
super.key,
|
|
required this.children,
|
|
this.crossAxisCount = 2,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return GridView.count(
|
|
shrinkWrap: true,
|
|
physics: const NeverScrollableScrollPhysics(),
|
|
crossAxisCount: crossAxisCount,
|
|
childAspectRatio: 1.2,
|
|
crossAxisSpacing: SpacingTokens.md,
|
|
mainAxisSpacing: SpacingTokens.md,
|
|
children: children,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Widget pour le drawer du dashboard
|
|
class DashboardDrawer extends StatelessWidget {
|
|
const DashboardDrawer({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Drawer(
|
|
child: ListView(
|
|
padding: EdgeInsets.zero,
|
|
children: [
|
|
const DrawerHeader(
|
|
decoration: BoxDecoration(
|
|
color: ColorTokens.primary,
|
|
),
|
|
child: Text(
|
|
'UnionFlow',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 24,
|
|
),
|
|
),
|
|
),
|
|
ListTile(
|
|
leading: const Icon(Icons.dashboard),
|
|
title: const Text('Dashboard'),
|
|
onTap: () {
|
|
Navigator.pop(context);
|
|
},
|
|
),
|
|
ListTile(
|
|
leading: const Icon(Icons.people),
|
|
title: const Text('Membres'),
|
|
onTap: () {
|
|
Navigator.pop(context);
|
|
},
|
|
),
|
|
ListTile(
|
|
leading: const Icon(Icons.event),
|
|
title: const Text('Événements'),
|
|
onTap: () {
|
|
Navigator.pop(context);
|
|
},
|
|
),
|
|
ListTile(
|
|
leading: const Icon(Icons.settings),
|
|
title: const Text('Paramètres'),
|
|
onTap: () {
|
|
Navigator.pop(context);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|