Clean project: remove test files, debug logs, and add documentation
This commit is contained in:
@@ -0,0 +1,460 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Widget réutilisable pour afficher un élément d'activité
|
||||
///
|
||||
/// Composant standardisé pour les listes d'activités récentes,
|
||||
/// notifications, historiques, etc.
|
||||
class ActivityItem extends StatelessWidget {
|
||||
/// Titre principal de l'activité
|
||||
final String title;
|
||||
|
||||
/// Description ou détails de l'activité
|
||||
final String? description;
|
||||
|
||||
/// Horodatage de l'activité
|
||||
final String timestamp;
|
||||
|
||||
/// Icône représentative de l'activité
|
||||
final IconData? icon;
|
||||
|
||||
/// Couleur thématique de l'activité
|
||||
final Color? color;
|
||||
|
||||
/// Type d'activité pour le style automatique
|
||||
final ActivityType? type;
|
||||
|
||||
/// Callback lors du tap sur l'élément
|
||||
final VoidCallback? onTap;
|
||||
|
||||
/// Style de l'élément d'activité
|
||||
final ActivityItemStyle style;
|
||||
|
||||
/// Afficher ou non l'indicateur de statut
|
||||
final bool showStatusIndicator;
|
||||
|
||||
const ActivityItem({
|
||||
super.key,
|
||||
required this.title,
|
||||
this.description,
|
||||
required this.timestamp,
|
||||
this.icon,
|
||||
this.color,
|
||||
this.type,
|
||||
this.onTap,
|
||||
this.style = ActivityItemStyle.normal,
|
||||
this.showStatusIndicator = true,
|
||||
});
|
||||
|
||||
/// Constructeur pour une activité système
|
||||
const ActivityItem.system({
|
||||
super.key,
|
||||
required this.title,
|
||||
this.description,
|
||||
required this.timestamp,
|
||||
this.onTap,
|
||||
}) : icon = Icons.settings,
|
||||
color = const Color(0xFF6C5CE7),
|
||||
type = ActivityType.system,
|
||||
style = ActivityItemStyle.normal,
|
||||
showStatusIndicator = true;
|
||||
|
||||
/// Constructeur pour une activité utilisateur
|
||||
const ActivityItem.user({
|
||||
super.key,
|
||||
required this.title,
|
||||
this.description,
|
||||
required this.timestamp,
|
||||
this.onTap,
|
||||
}) : icon = Icons.person,
|
||||
color = const Color(0xFF00B894),
|
||||
type = ActivityType.user,
|
||||
style = ActivityItemStyle.normal,
|
||||
showStatusIndicator = true;
|
||||
|
||||
/// Constructeur pour une alerte
|
||||
const ActivityItem.alert({
|
||||
super.key,
|
||||
required this.title,
|
||||
this.description,
|
||||
required this.timestamp,
|
||||
this.onTap,
|
||||
}) : icon = Icons.warning,
|
||||
color = Colors.orange,
|
||||
type = ActivityType.alert,
|
||||
style = ActivityItemStyle.alert,
|
||||
showStatusIndicator = true;
|
||||
|
||||
/// Constructeur pour une erreur
|
||||
const ActivityItem.error({
|
||||
super.key,
|
||||
required this.title,
|
||||
this.description,
|
||||
required this.timestamp,
|
||||
this.onTap,
|
||||
}) : icon = Icons.error,
|
||||
color = Colors.red,
|
||||
type = ActivityType.error,
|
||||
style = ActivityItemStyle.alert,
|
||||
showStatusIndicator = true;
|
||||
|
||||
/// Constructeur pour une activité de succès
|
||||
const ActivityItem.success({
|
||||
super.key,
|
||||
required this.title,
|
||||
this.description,
|
||||
required this.timestamp,
|
||||
this.onTap,
|
||||
}) : icon = Icons.check_circle,
|
||||
color = const Color(0xFF00B894),
|
||||
type = ActivityType.success,
|
||||
style = ActivityItemStyle.normal,
|
||||
showStatusIndicator = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final effectiveColor = _getEffectiveColor();
|
||||
final effectiveIcon = _getEffectiveIcon();
|
||||
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
padding: _getPadding(),
|
||||
decoration: _getDecoration(effectiveColor),
|
||||
child: _buildContent(effectiveColor, effectiveIcon),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Contenu principal de l'élément
|
||||
Widget _buildContent(Color effectiveColor, IconData effectiveIcon) {
|
||||
switch (style) {
|
||||
case ActivityItemStyle.minimal:
|
||||
return _buildMinimalContent(effectiveColor, effectiveIcon);
|
||||
case ActivityItemStyle.normal:
|
||||
return _buildNormalContent(effectiveColor, effectiveIcon);
|
||||
case ActivityItemStyle.detailed:
|
||||
return _buildDetailedContent(effectiveColor, effectiveIcon);
|
||||
case ActivityItemStyle.alert:
|
||||
return _buildAlertContent(effectiveColor, effectiveIcon);
|
||||
}
|
||||
}
|
||||
|
||||
/// Contenu minimal (ligne simple)
|
||||
Widget _buildMinimalContent(Color effectiveColor, IconData effectiveIcon) {
|
||||
return Row(
|
||||
children: [
|
||||
if (showStatusIndicator)
|
||||
Container(
|
||||
width: 8,
|
||||
height: 8,
|
||||
decoration: BoxDecoration(
|
||||
color: effectiveColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
if (showStatusIndicator) const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
timestamp,
|
||||
style: const TextStyle(
|
||||
color: Colors.grey,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Contenu normal avec icône
|
||||
Widget _buildNormalContent(Color effectiveColor, IconData effectiveIcon) {
|
||||
return Row(
|
||||
children: [
|
||||
if (showStatusIndicator) ...[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(6),
|
||||
decoration: BoxDecoration(
|
||||
color: effectiveColor.withOpacity(0.1),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
effectiveIcon,
|
||||
color: effectiveColor,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
],
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF1F2937),
|
||||
),
|
||||
),
|
||||
if (description != null) ...[
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
description!,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
timestamp,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[500],
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Contenu détaillé avec plus d'informations
|
||||
Widget _buildDetailedContent(Color effectiveColor, IconData effectiveIcon) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: effectiveColor.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Icon(
|
||||
effectiveIcon,
|
||||
color: effectiveColor,
|
||||
size: 18,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF1F2937),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
timestamp,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[500],
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (description != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 42),
|
||||
child: Text(
|
||||
description!,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey[700],
|
||||
height: 1.4,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Contenu pour les alertes avec style spécial
|
||||
Widget _buildAlertContent(Color effectiveColor, IconData effectiveIcon) {
|
||||
return Row(
|
||||
children: [
|
||||
Icon(
|
||||
effectiveIcon,
|
||||
color: effectiveColor,
|
||||
size: 18,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: effectiveColor,
|
||||
),
|
||||
),
|
||||
if (description != null) ...[
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
description!,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
timestamp,
|
||||
style: TextStyle(
|
||||
color: Colors.grey[500],
|
||||
fontSize: 11,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// Couleur effective selon le type
|
||||
Color _getEffectiveColor() {
|
||||
if (color != null) return color!;
|
||||
|
||||
switch (type) {
|
||||
case ActivityType.system:
|
||||
return const Color(0xFF6C5CE7);
|
||||
case ActivityType.user:
|
||||
return const Color(0xFF00B894);
|
||||
case ActivityType.organization:
|
||||
return const Color(0xFF0984E3);
|
||||
case ActivityType.event:
|
||||
return const Color(0xFFE17055);
|
||||
case ActivityType.alert:
|
||||
return Colors.orange;
|
||||
case ActivityType.error:
|
||||
return Colors.red;
|
||||
case ActivityType.success:
|
||||
return const Color(0xFF00B894);
|
||||
case null:
|
||||
return const Color(0xFF6C5CE7);
|
||||
}
|
||||
}
|
||||
|
||||
/// Icône effective selon le type
|
||||
IconData _getEffectiveIcon() {
|
||||
if (icon != null) return icon!;
|
||||
|
||||
switch (type) {
|
||||
case ActivityType.system:
|
||||
return Icons.settings;
|
||||
case ActivityType.user:
|
||||
return Icons.person;
|
||||
case ActivityType.organization:
|
||||
return Icons.business;
|
||||
case ActivityType.event:
|
||||
return Icons.event;
|
||||
case ActivityType.alert:
|
||||
return Icons.warning;
|
||||
case ActivityType.error:
|
||||
return Icons.error;
|
||||
case ActivityType.success:
|
||||
return Icons.check_circle;
|
||||
case null:
|
||||
return Icons.circle;
|
||||
}
|
||||
}
|
||||
|
||||
/// Padding selon le style
|
||||
EdgeInsets _getPadding() {
|
||||
switch (style) {
|
||||
case ActivityItemStyle.minimal:
|
||||
return const EdgeInsets.symmetric(vertical: 4, horizontal: 8);
|
||||
case ActivityItemStyle.normal:
|
||||
return const EdgeInsets.all(8);
|
||||
case ActivityItemStyle.detailed:
|
||||
return const EdgeInsets.all(12);
|
||||
case ActivityItemStyle.alert:
|
||||
return const EdgeInsets.all(10);
|
||||
}
|
||||
}
|
||||
|
||||
/// Décoration selon le style
|
||||
BoxDecoration _getDecoration(Color effectiveColor) {
|
||||
switch (style) {
|
||||
case ActivityItemStyle.minimal:
|
||||
return const BoxDecoration();
|
||||
case ActivityItemStyle.normal:
|
||||
return BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.02),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 1),
|
||||
),
|
||||
],
|
||||
);
|
||||
case ActivityItemStyle.detailed:
|
||||
return BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
);
|
||||
case ActivityItemStyle.alert:
|
||||
return BoxDecoration(
|
||||
color: effectiveColor.withOpacity(0.05),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: effectiveColor.withOpacity(0.2),
|
||||
width: 1,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Types d'activité
|
||||
enum ActivityType {
|
||||
system,
|
||||
user,
|
||||
organization,
|
||||
event,
|
||||
alert,
|
||||
error,
|
||||
success,
|
||||
}
|
||||
|
||||
/// Styles d'élément d'activité
|
||||
enum ActivityItemStyle {
|
||||
minimal,
|
||||
normal,
|
||||
detailed,
|
||||
alert,
|
||||
}
|
||||
Reference in New Issue
Block a user