Files
unionflow-server-api/unionflow-mobile-apps/lib/features/dashboard/presentation/widgets/dashboard_widgets.dart
2025-11-17 16:02:04 +00:00

256 lines
6.6 KiB
Dart

import 'package:flutter/material.dart';
import '../../../../shared/design_system/dashboard_theme.dart';
/// Widget de statistique simple pour les dashboards de rôle
class DashboardStat extends StatelessWidget {
final String title;
final String value;
final IconData icon;
final Color? color;
const DashboardStat({
super.key,
required this.title,
required this.value,
required this.icon,
this.color,
});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(DashboardTheme.spacing16),
decoration: BoxDecoration(
color: DashboardTheme.white,
borderRadius: BorderRadius.circular(DashboardTheme.borderRadius),
boxShadow: DashboardTheme.cardShadow,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(
icon,
color: color ?? DashboardTheme.royalBlue,
size: 24,
),
const Spacer(),
Text(
value,
style: DashboardTheme.titleLarge.copyWith(
color: color ?? DashboardTheme.royalBlue,
),
),
],
),
const SizedBox(height: DashboardTheme.spacing8),
Text(
title,
style: DashboardTheme.bodyMedium,
),
],
),
);
}
}
/// Widget de grille de statistiques
class DashboardStatsGrid extends StatelessWidget {
final List<DashboardStat> stats;
final Function(String)? onStatTap;
const DashboardStatsGrid({
super.key,
required this.stats,
this.onStatTap,
});
@override
Widget build(BuildContext context) {
return GridView.count(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: 2,
mainAxisSpacing: DashboardTheme.spacing12,
crossAxisSpacing: DashboardTheme.spacing12,
childAspectRatio: 1.2,
children: stats,
);
}
}
/// Widget de grille d'actions rapides
class DashboardQuickActionsGrid extends StatelessWidget {
final List<Widget> children;
const DashboardQuickActionsGrid({
super.key,
required this.children,
});
@override
Widget build(BuildContext context) {
return GridView.count(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
crossAxisCount: 2,
mainAxisSpacing: DashboardTheme.spacing12,
crossAxisSpacing: DashboardTheme.spacing12,
childAspectRatio: 1.5,
children: children,
);
}
}
/// Widget d'action rapide
class DashboardQuickAction extends StatelessWidget {
final String title;
final IconData icon;
final VoidCallback onTap;
final Color? color;
const DashboardQuickAction({
super.key,
required this.title,
required this.icon,
required this.onTap,
this.color,
});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(DashboardTheme.borderRadius),
child: Container(
padding: const EdgeInsets.all(DashboardTheme.spacing16),
decoration: BoxDecoration(
color: DashboardTheme.white,
borderRadius: BorderRadius.circular(DashboardTheme.borderRadius),
boxShadow: DashboardTheme.cardShadow,
border: Border.all(
color: (color ?? DashboardTheme.royalBlue).withOpacity(0.2),
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
color: color ?? DashboardTheme.royalBlue,
size: 32,
),
const SizedBox(height: DashboardTheme.spacing8),
Text(
title,
style: DashboardTheme.bodyMedium.copyWith(
fontWeight: FontWeight.w600,
),
textAlign: TextAlign.center,
),
],
),
),
);
}
}
/// Widget de section d'activités récentes
class DashboardRecentActivitySection extends StatelessWidget {
final List<Widget> children;
const DashboardRecentActivitySection({
super.key,
required this.children,
});
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(DashboardTheme.spacing16),
decoration: BoxDecoration(
color: DashboardTheme.white,
borderRadius: BorderRadius.circular(DashboardTheme.borderRadius),
boxShadow: DashboardTheme.cardShadow,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Activités récentes',
style: DashboardTheme.titleMedium,
),
const SizedBox(height: DashboardTheme.spacing16),
...children,
],
),
);
}
}
/// Widget d'activité
class DashboardActivity extends StatelessWidget {
final String title;
final String subtitle;
final String time;
final IconData icon;
final Color? color;
const DashboardActivity({
super.key,
required this.title,
required this.subtitle,
required this.time,
required this.icon,
this.color,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(bottom: DashboardTheme.spacing12),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(DashboardTheme.spacing8),
decoration: BoxDecoration(
color: (color ?? DashboardTheme.royalBlue).withOpacity(0.1),
borderRadius: BorderRadius.circular(DashboardTheme.borderRadiusSmall),
),
child: Icon(
icon,
color: color ?? DashboardTheme.royalBlue,
size: 16,
),
),
const SizedBox(width: DashboardTheme.spacing12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: DashboardTheme.bodyMedium.copyWith(
fontWeight: FontWeight.w600,
),
),
Text(
subtitle,
style: DashboardTheme.bodySmall,
),
],
),
),
Text(
time,
style: DashboardTheme.bodySmall.copyWith(
color: DashboardTheme.grey500,
),
),
],
),
);
}
}