Files
unionflow-server-impl-quarkus/unionflow-mobile-apps/lib/features/notifications/presentation/widgets/notification_stats_widget.dart
2025-09-17 17:54:06 +00:00

401 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import '../../../../core/widgets/unified_card.dart';
import '../../../../core/theme/app_colors.dart';
import '../../../../core/theme/app_text_styles.dart';
/// Widget d'affichage des statistiques de notifications
class NotificationStatsWidget extends StatelessWidget {
final int totalCount;
final int unreadCount;
final int importantCount;
const NotificationStatsWidget({
super.key,
required this.totalCount,
required this.unreadCount,
required this.importantCount,
});
@override
Widget build(BuildContext context) {
return UnifiedCard(
variant: UnifiedCardVariant.filled,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
// Statistique principale - Non lues
Expanded(
child: _buildStatItem(
icon: Icons.mark_email_unread,
label: 'Non lues',
value: unreadCount.toString(),
color: unreadCount > 0 ? AppColors.primary : AppColors.onSurface.withOpacity(0.6),
isHighlighted: unreadCount > 0,
),
),
// Séparateur
Container(
width: 1,
height: 40,
color: AppColors.outline.withOpacity(0.2),
),
// Statistique secondaire - Importantes
Expanded(
child: _buildStatItem(
icon: Icons.star,
label: 'Importantes',
value: importantCount.toString(),
color: importantCount > 0 ? AppColors.warning : AppColors.onSurface.withOpacity(0.6),
isHighlighted: importantCount > 0,
),
),
// Séparateur
Container(
width: 1,
height: 40,
color: AppColors.outline.withOpacity(0.2),
),
// Statistique tertiaire - Total
Expanded(
child: _buildStatItem(
icon: Icons.notifications,
label: 'Total',
value: totalCount.toString(),
color: AppColors.onSurface.withOpacity(0.8),
isHighlighted: false,
),
),
],
),
),
);
}
Widget _buildStatItem({
required IconData icon,
required String label,
required String value,
required Color color,
required bool isHighlighted,
}) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// Icône avec badge si mis en évidence
Stack(
clipBehavior: Clip.none,
children: [
Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(
icon,
color: color,
size: 18,
),
),
if (isHighlighted && value != '0')
Positioned(
right: -4,
top: -4,
child: Container(
width: 12,
height: 12,
decoration: BoxDecoration(
color: color,
shape: BoxShape.circle,
border: Border.all(
color: AppColors.surface,
width: 2,
),
),
),
),
],
),
const SizedBox(height: 8),
// Valeur
Text(
value,
style: AppTextStyles.titleMedium.copyWith(
color: color,
fontWeight: isHighlighted ? FontWeight.w700 : FontWeight.w600,
),
),
const SizedBox(height: 2),
// Label
Text(
label,
style: AppTextStyles.labelSmall.copyWith(
color: AppColors.onSurface.withOpacity(0.7),
),
textAlign: TextAlign.center,
),
],
);
}
}
/// Widget d'affichage des statistiques détaillées
class DetailedNotificationStatsWidget extends StatelessWidget {
final Map<String, dynamic> stats;
const DetailedNotificationStatsWidget({
super.key,
required this.stats,
});
@override
Widget build(BuildContext context) {
final totalNotifications = stats['total'] ?? 0;
final unreadNotifications = stats['unread'] ?? 0;
final importantNotifications = stats['important'] ?? 0;
final archivedNotifications = stats['archived'] ?? 0;
final todayNotifications = stats['today'] ?? 0;
final weekNotifications = stats['week'] ?? 0;
final engagementRate = stats['engagement_rate'] ?? 0.0;
return UnifiedCard(
variant: UnifiedCardVariant.outlined,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// En-tête
Row(
children: [
Icon(
Icons.analytics,
color: AppColors.primary,
size: 24,
),
const SizedBox(width: 12),
Text(
'Statistiques détaillées',
style: AppTextStyles.titleMedium.copyWith(
fontWeight: FontWeight.w600,
),
),
],
),
const SizedBox(height: 20),
// Grille de statistiques
GridView.count(
crossAxisCount: 2,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
childAspectRatio: 2.5,
mainAxisSpacing: 16,
crossAxisSpacing: 16,
children: [
_buildDetailedStatCard(
'Total',
totalNotifications.toString(),
Icons.notifications,
AppColors.primary,
),
_buildDetailedStatCard(
'Non lues',
unreadNotifications.toString(),
Icons.mark_email_unread,
AppColors.warning,
),
_buildDetailedStatCard(
'Importantes',
importantNotifications.toString(),
Icons.star,
AppColors.error,
),
_buildDetailedStatCard(
'Archivées',
archivedNotifications.toString(),
Icons.archive,
AppColors.onSurface.withOpacity(0.6),
),
],
),
const SizedBox(height: 20),
// Statistiques temporelles
Row(
children: [
Expanded(
child: _buildTimeStatCard(
'Aujourd\'hui',
todayNotifications.toString(),
Icons.today,
),
),
const SizedBox(width: 16),
Expanded(
child: _buildTimeStatCard(
'Cette semaine',
weekNotifications.toString(),
Icons.date_range,
),
),
],
),
const SizedBox(height: 20),
// Taux d'engagement
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppColors.primaryContainer.withOpacity(0.3),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: AppColors.primary.withOpacity(0.2),
),
),
child: Row(
children: [
Icon(
Icons.trending_up,
color: AppColors.primary,
size: 20,
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Taux d\'engagement',
style: AppTextStyles.labelMedium.copyWith(
color: AppColors.primary,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 2),
Text(
'Pourcentage de notifications ouvertes',
style: AppTextStyles.bodySmall.copyWith(
color: AppColors.onSurface.withOpacity(0.7),
),
),
],
),
),
Text(
'${engagementRate.toStringAsFixed(1)}%',
style: AppTextStyles.titleMedium.copyWith(
color: AppColors.primary,
fontWeight: FontWeight.w700,
),
),
],
),
),
],
),
),
);
}
Widget _buildDetailedStatCard(
String label,
String value,
IconData icon,
Color color,
) {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: color.withOpacity(0.05),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: color.withOpacity(0.2),
),
),
child: Row(
children: [
Icon(
icon,
color: color,
size: 20,
),
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
value,
style: AppTextStyles.titleSmall.copyWith(
color: color,
fontWeight: FontWeight.w700,
),
),
Text(
label,
style: AppTextStyles.labelSmall.copyWith(
color: AppColors.onSurface.withOpacity(0.7),
),
),
],
),
),
],
),
);
}
Widget _buildTimeStatCard(String label, String value, IconData icon) {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: AppColors.surfaceVariant.withOpacity(0.5),
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: AppColors.outline.withOpacity(0.2),
),
),
child: Column(
children: [
Icon(
icon,
color: AppColors.onSurfaceVariant,
size: 20,
),
const SizedBox(height: 8),
Text(
value,
style: AppTextStyles.titleSmall.copyWith(
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 2),
Text(
label,
style: AppTextStyles.labelSmall.copyWith(
color: AppColors.onSurface.withOpacity(0.7),
),
textAlign: TextAlign.center,
),
],
),
);
}
}