Files
unionflow-client-quarkus-pr…/unionflow-mobile-apps/lib/features/dashboard/presentation/widgets/dashboard_widgets.dart
2025-09-20 03:56:11 +00:00

298 lines
7.2 KiB
Dart

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: [
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);
},
),
],
),
);
}
}