Files
unionflow-client-quarkus-pr…/unionflow-mobile-apps/lib/features/dashboard/presentation/widgets/recent_activities_section.dart

367 lines
9.9 KiB
Dart

import 'package:flutter/material.dart';
import 'common/activity_item.dart';
/// Section des activités récentes du dashboard
///
/// Widget réutilisable pour afficher les dernières activités,
/// notifications, logs ou événements selon le contexte.
class RecentActivitiesSection extends StatelessWidget {
/// Titre de la section
final String title;
/// Sous-titre optionnel
final String? subtitle;
/// Liste des activités à afficher
final List<RecentActivity> activities;
/// Nombre maximum d'activités à afficher
final int maxItems;
/// Style des éléments d'activité
final ActivityItemStyle itemStyle;
/// Callback lors du tap sur une activité
final Function(RecentActivity)? onActivityTap;
/// Callback pour voir toutes les activités
final VoidCallback? onViewAll;
/// Afficher ou non l'en-tête de section
final bool showHeader;
/// Afficher ou non le bouton "Voir tout"
final bool showViewAll;
/// Message à afficher si aucune activité
final String? emptyMessage;
const RecentActivitiesSection({
super.key,
required this.title,
this.subtitle,
required this.activities,
this.maxItems = 5,
this.itemStyle = ActivityItemStyle.normal,
this.onActivityTap,
this.onViewAll,
this.showHeader = true,
this.showViewAll = true,
this.emptyMessage,
});
/// Constructeur pour les activités système (Super Admin)
const RecentActivitiesSection.system({
super.key,
this.onActivityTap,
this.onViewAll,
}) : title = 'Activité Système',
subtitle = 'Événements récents',
activities = const [
RecentActivity(
title: 'Sauvegarde automatique terminée',
description: 'Sauvegarde complète réussie (2.3 GB)',
timestamp: 'il y a 1h',
type: ActivityType.system,
),
RecentActivity(
title: 'Nouvelle organisation créée',
description: 'TechCorp a rejoint la plateforme',
timestamp: 'il y a 2h',
type: ActivityType.organization,
),
RecentActivity(
title: 'Mise à jour système',
description: 'Version 2.1.0 déployée avec succès',
timestamp: 'il y a 4h',
type: ActivityType.system,
),
RecentActivity(
title: 'Alerte CPU résolue',
description: 'Charge CPU revenue à la normale',
timestamp: 'il y a 6h',
type: ActivityType.success,
),
],
maxItems = 4,
itemStyle = ActivityItemStyle.normal,
showHeader = true,
showViewAll = true,
emptyMessage = null;
/// Constructeur pour les activités d'organisation
const RecentActivitiesSection.organization({
super.key,
this.onActivityTap,
this.onViewAll,
}) : title = 'Activité Récente',
subtitle = null,
activities = const [
RecentActivity(
title: 'Nouveau membre inscrit',
description: 'Marie Dubois a rejoint l\'organisation',
timestamp: 'il y a 30min',
type: ActivityType.user,
),
RecentActivity(
title: 'Événement créé',
description: 'Réunion mensuelle programmée',
timestamp: 'il y a 2h',
type: ActivityType.event,
),
RecentActivity(
title: 'Document partagé',
description: 'Rapport Q4 2024 publié',
timestamp: 'il y a 1j',
type: ActivityType.organization,
),
],
maxItems = 3,
itemStyle = ActivityItemStyle.normal,
showHeader = true,
showViewAll = true,
emptyMessage = null;
/// Constructeur pour les alertes système
const RecentActivitiesSection.alerts({
super.key,
this.onActivityTap,
this.onViewAll,
}) : title = 'Alertes Récentes',
subtitle = 'Notifications importantes',
activities = const [
RecentActivity(
title: 'Charge CPU élevée',
description: 'Serveur principal à 85%',
timestamp: 'il y a 15min',
type: ActivityType.alert,
),
RecentActivity(
title: 'Espace disque faible',
description: 'Base de données à 90%',
timestamp: 'il y a 1h',
type: ActivityType.error,
),
RecentActivity(
title: 'Connexions élevées',
description: 'Load balancer surchargé',
timestamp: 'il y a 2h',
type: ActivityType.alert,
),
],
maxItems = 3,
itemStyle = ActivityItemStyle.alert,
showHeader = true,
showViewAll = true,
emptyMessage = null;
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (showHeader) _buildHeader(),
const SizedBox(height: 12),
_buildActivitiesList(),
],
),
);
}
/// En-tête de la section
Widget _buildHeader() {
return Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Color(0xFF6C5CE7),
),
),
if (subtitle != null) ...[
const SizedBox(height: 2),
Text(
subtitle!,
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
),
],
],
),
),
if (showViewAll && onViewAll != null)
TextButton(
onPressed: onViewAll,
child: const Text(
'Voir tout',
style: TextStyle(
fontSize: 12,
color: Color(0xFF6C5CE7),
fontWeight: FontWeight.w600,
),
),
),
],
);
}
/// Liste des activités
Widget _buildActivitiesList() {
if (activities.isEmpty) {
return _buildEmptyState();
}
final displayedActivities = activities.take(maxItems).toList();
return Column(
children: displayedActivities.map((activity) => ActivityItem(
title: activity.title,
description: activity.description,
timestamp: activity.timestamp,
icon: activity.icon,
color: activity.color,
type: activity.type,
style: itemStyle,
onTap: onActivityTap != null ? () => onActivityTap!(activity) : null,
)).toList(),
);
}
/// État vide
Widget _buildEmptyState() {
return Container(
padding: const EdgeInsets.all(24),
child: Column(
children: [
Icon(
Icons.inbox_outlined,
size: 48,
color: Colors.grey[400],
),
const SizedBox(height: 12),
Text(
emptyMessage ?? 'Aucune activité récente',
style: TextStyle(
fontSize: 14,
color: Colors.grey[600],
),
textAlign: TextAlign.center,
),
],
),
);
}
}
/// Modèle de données pour une activité récente
class RecentActivity {
final String title;
final String? description;
final String timestamp;
final IconData? icon;
final Color? color;
final ActivityType? type;
final Map<String, dynamic>? metadata;
const RecentActivity({
required this.title,
this.description,
required this.timestamp,
this.icon,
this.color,
this.type,
this.metadata,
});
/// Constructeur pour une activité système
const RecentActivity.system({
required this.title,
this.description,
required this.timestamp,
this.metadata,
}) : icon = Icons.settings,
color = const Color(0xFF6C5CE7),
type = ActivityType.system;
/// Constructeur pour une activité utilisateur
const RecentActivity.user({
required this.title,
this.description,
required this.timestamp,
this.metadata,
}) : icon = Icons.person,
color = const Color(0xFF00B894),
type = ActivityType.user;
/// Constructeur pour une activité d'organisation
const RecentActivity.organization({
required this.title,
this.description,
required this.timestamp,
this.metadata,
}) : icon = Icons.business,
color = const Color(0xFF0984E3),
type = ActivityType.organization;
/// Constructeur pour une activité d'événement
const RecentActivity.event({
required this.title,
this.description,
required this.timestamp,
this.metadata,
}) : icon = Icons.event,
color = const Color(0xFFE17055),
type = ActivityType.event;
/// Constructeur pour une alerte
const RecentActivity.alert({
required this.title,
this.description,
required this.timestamp,
this.metadata,
}) : icon = Icons.warning,
color = Colors.orange,
type = ActivityType.alert;
/// Constructeur pour une erreur
const RecentActivity.error({
required this.title,
this.description,
required this.timestamp,
this.metadata,
}) : icon = Icons.error,
color = Colors.red,
type = ActivityType.error;
/// Constructeur pour un succès
const RecentActivity.success({
required this.title,
this.description,
required this.timestamp,
this.metadata,
}) : icon = Icons.check_circle,
color = const Color(0xFF00B894),
type = ActivityType.success;
}