360 lines
10 KiB
Dart
360 lines
10 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'common/section_header.dart';
|
|
|
|
/// Widget d'en-tête principal du dashboard
|
|
///
|
|
/// Composant réutilisable pour l'en-tête des dashboards avec
|
|
/// informations système, statut et actions rapides.
|
|
class DashboardHeader extends StatelessWidget {
|
|
/// Titre principal du dashboard
|
|
final String title;
|
|
|
|
/// Sous-titre ou description
|
|
final String? subtitle;
|
|
|
|
/// Afficher les informations système
|
|
final bool showSystemInfo;
|
|
|
|
/// Afficher les actions rapides
|
|
final bool showQuickActions;
|
|
|
|
/// Callback pour les actions personnalisées
|
|
final List<DashboardAction>? actions;
|
|
|
|
/// Métriques système à afficher
|
|
final List<SystemMetric>? systemMetrics;
|
|
|
|
/// Style de l'en-tête
|
|
final DashboardHeaderStyle style;
|
|
|
|
const DashboardHeader({
|
|
super.key,
|
|
required this.title,
|
|
this.subtitle,
|
|
this.showSystemInfo = true,
|
|
this.showQuickActions = true,
|
|
this.actions,
|
|
this.systemMetrics,
|
|
this.style = DashboardHeaderStyle.gradient,
|
|
});
|
|
|
|
/// Constructeur pour un en-tête Super Admin
|
|
const DashboardHeader.superAdmin({
|
|
super.key,
|
|
this.actions,
|
|
}) : title = 'Administration Système',
|
|
subtitle = 'Surveillance et gestion globale',
|
|
showSystemInfo = true,
|
|
showQuickActions = true,
|
|
systemMetrics = null,
|
|
style = DashboardHeaderStyle.gradient;
|
|
|
|
/// Constructeur pour un en-tête Admin Organisation
|
|
const DashboardHeader.orgAdmin({
|
|
super.key,
|
|
this.actions,
|
|
}) : title = 'Administration Organisation',
|
|
subtitle = 'Gestion de votre organisation',
|
|
showSystemInfo = false,
|
|
showQuickActions = true,
|
|
systemMetrics = null,
|
|
style = DashboardHeaderStyle.gradient;
|
|
|
|
/// Constructeur pour un en-tête Membre
|
|
const DashboardHeader.member({
|
|
super.key,
|
|
this.actions,
|
|
}) : title = 'Tableau de bord',
|
|
subtitle = 'Bienvenue dans UnionFlow',
|
|
showSystemInfo = false,
|
|
showQuickActions = false,
|
|
systemMetrics = null,
|
|
style = DashboardHeaderStyle.simple;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
switch (style) {
|
|
case DashboardHeaderStyle.gradient:
|
|
return _buildGradientHeader();
|
|
case DashboardHeaderStyle.simple:
|
|
return _buildSimpleHeader();
|
|
case DashboardHeaderStyle.card:
|
|
return _buildCardHeader();
|
|
}
|
|
}
|
|
|
|
/// En-tête avec gradient (style principal)
|
|
Widget _buildGradientHeader() {
|
|
return Container(
|
|
margin: const EdgeInsets.all(12),
|
|
padding: const EdgeInsets.all(20),
|
|
decoration: BoxDecoration(
|
|
gradient: const LinearGradient(
|
|
colors: [Color(0xFF6C5CE7), Color(0xFF5A4FCF)],
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
),
|
|
borderRadius: BorderRadius.circular(16),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: const Color(0xFF6C5CE7).withOpacity(0.3),
|
|
blurRadius: 20,
|
|
offset: const Offset(0, 8),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
_buildHeaderContent(),
|
|
if (showSystemInfo && systemMetrics != null) ...[
|
|
const SizedBox(height: 16),
|
|
_buildSystemMetrics(),
|
|
],
|
|
if (showQuickActions && actions != null) ...[
|
|
const SizedBox(height: 16),
|
|
_buildQuickActions(),
|
|
],
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
/// En-tête simple sans fond
|
|
Widget _buildSimpleHeader() {
|
|
return Padding(
|
|
padding: const EdgeInsets.all(16),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SectionHeader.primary(
|
|
title: title,
|
|
subtitle: subtitle,
|
|
action: actions?.isNotEmpty == true ? _buildActionsRow() : null,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
/// En-tête avec fond de carte
|
|
Widget _buildCardHeader() {
|
|
return Container(
|
|
margin: const EdgeInsets.all(12),
|
|
padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(16),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.05),
|
|
blurRadius: 10,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
_buildHeaderContent(isWhiteBackground: true),
|
|
if (showSystemInfo && systemMetrics != null) ...[
|
|
const SizedBox(height: 16),
|
|
_buildSystemMetrics(isWhiteBackground: true),
|
|
],
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Contenu principal de l'en-tête
|
|
Widget _buildHeaderContent({bool isWhiteBackground = false}) {
|
|
final textColor = isWhiteBackground ? const Color(0xFF1F2937) : Colors.white;
|
|
final subtitleColor = isWhiteBackground ? Colors.grey[600] : Colors.white.withOpacity(0.8);
|
|
|
|
return Row(
|
|
children: [
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
title,
|
|
style: TextStyle(
|
|
fontSize: 24,
|
|
fontWeight: FontWeight.bold,
|
|
color: textColor,
|
|
),
|
|
),
|
|
if (subtitle != null) ...[
|
|
const SizedBox(height: 4),
|
|
Text(
|
|
subtitle!,
|
|
style: TextStyle(
|
|
fontSize: 16,
|
|
color: subtitleColor,
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
if (actions?.isNotEmpty == true) _buildActionsRow(isWhiteBackground: isWhiteBackground),
|
|
],
|
|
);
|
|
}
|
|
|
|
/// Métriques système
|
|
Widget _buildSystemMetrics({bool isWhiteBackground = false}) {
|
|
if (systemMetrics == null || systemMetrics!.isEmpty) {
|
|
return _buildDefaultSystemMetrics(isWhiteBackground: isWhiteBackground);
|
|
}
|
|
|
|
return Wrap(
|
|
spacing: 12,
|
|
runSpacing: 8,
|
|
children: systemMetrics!.map((metric) => _buildMetricChip(
|
|
metric.label,
|
|
metric.value,
|
|
metric.icon,
|
|
isWhiteBackground: isWhiteBackground,
|
|
)).toList(),
|
|
);
|
|
}
|
|
|
|
/// Métriques système par défaut
|
|
Widget _buildDefaultSystemMetrics({bool isWhiteBackground = false}) {
|
|
return Row(
|
|
children: [
|
|
Expanded(child: _buildMetricChip('Uptime', '99.97%', Icons.trending_up, isWhiteBackground: isWhiteBackground)),
|
|
const SizedBox(width: 12),
|
|
Expanded(child: _buildMetricChip('CPU', '23%', Icons.memory, isWhiteBackground: isWhiteBackground)),
|
|
const SizedBox(width: 12),
|
|
Expanded(child: _buildMetricChip('Users', '1,247', Icons.people, isWhiteBackground: isWhiteBackground)),
|
|
],
|
|
);
|
|
}
|
|
|
|
/// Chip de métrique
|
|
Widget _buildMetricChip(String label, String value, IconData icon, {bool isWhiteBackground = false}) {
|
|
final backgroundColor = isWhiteBackground
|
|
? const Color(0xFF6C5CE7).withOpacity(0.1)
|
|
: Colors.white.withOpacity(0.15);
|
|
final textColor = isWhiteBackground ? const Color(0xFF6C5CE7) : Colors.white;
|
|
|
|
return Container(
|
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
decoration: BoxDecoration(
|
|
color: backgroundColor,
|
|
borderRadius: BorderRadius.circular(20),
|
|
),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Icon(icon, color: textColor, size: 16),
|
|
const SizedBox(width: 6),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
value,
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
fontWeight: FontWeight.bold,
|
|
color: textColor,
|
|
),
|
|
),
|
|
Text(
|
|
label,
|
|
style: TextStyle(
|
|
fontSize: 10,
|
|
color: textColor.withOpacity(0.8),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
/// Actions rapides
|
|
Widget _buildQuickActions({bool isWhiteBackground = false}) {
|
|
if (actions == null || actions!.isEmpty) return const SizedBox.shrink();
|
|
|
|
return Row(
|
|
children: actions!.map((action) => Expanded(
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 4),
|
|
child: _buildActionButton(action, isWhiteBackground: isWhiteBackground),
|
|
),
|
|
)).toList(),
|
|
);
|
|
}
|
|
|
|
/// Ligne d'actions
|
|
Widget _buildActionsRow({bool isWhiteBackground = false}) {
|
|
if (actions == null || actions!.isEmpty) return const SizedBox.shrink();
|
|
|
|
return Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: actions!.map((action) => Padding(
|
|
padding: const EdgeInsets.only(left: 8),
|
|
child: _buildActionButton(action, isWhiteBackground: isWhiteBackground),
|
|
)).toList(),
|
|
);
|
|
}
|
|
|
|
/// Bouton d'action
|
|
Widget _buildActionButton(DashboardAction action, {bool isWhiteBackground = false}) {
|
|
final backgroundColor = isWhiteBackground
|
|
? Colors.white
|
|
: Colors.white.withOpacity(0.2);
|
|
final iconColor = isWhiteBackground ? const Color(0xFF6C5CE7) : Colors.white;
|
|
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: backgroundColor,
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: IconButton(
|
|
onPressed: action.onPressed,
|
|
icon: Icon(action.icon, color: iconColor),
|
|
tooltip: action.tooltip,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Action du dashboard
|
|
class DashboardAction {
|
|
final IconData icon;
|
|
final String tooltip;
|
|
final VoidCallback onPressed;
|
|
|
|
const DashboardAction({
|
|
required this.icon,
|
|
required this.tooltip,
|
|
required this.onPressed,
|
|
});
|
|
}
|
|
|
|
/// Métrique système
|
|
class SystemMetric {
|
|
final String label;
|
|
final String value;
|
|
final IconData icon;
|
|
|
|
const SystemMetric({
|
|
required this.label,
|
|
required this.value,
|
|
required this.icon,
|
|
});
|
|
}
|
|
|
|
/// Styles d'en-tête de dashboard
|
|
enum DashboardHeaderStyle {
|
|
gradient,
|
|
simple,
|
|
card,
|
|
}
|