import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:fl_chart/fl_chart.dart'; import '../../../../../shared/design_system/unionflow_design_v2.dart'; import '../../bloc/dashboard_bloc.dart'; import '../../widgets/dashboard_drawer.dart'; import '../../../../authentication/presentation/bloc/auth_bloc.dart'; import '../../../../reports/presentation/pages/reports_page_wrapper.dart'; import '../../../../members/presentation/pages/members_page_wrapper.dart'; import '../../../../events/presentation/pages/events_page_wrapper.dart'; import '../../../../help/presentation/pages/help_support_page.dart'; /// Dashboard Consultant - Design UnionFlow Expertise & Analyses class ConsultantDashboard extends StatelessWidget { const ConsultantDashboard({super.key}); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: UnionFlowColors.background, appBar: _buildAppBar(context), drawer: DashboardDrawer( onNavigate: (route) => Navigator.of(context).pushNamed(route), onLogout: () => context.read().add(const AuthLogoutRequested()), ), body: AfricanPatternBackground( child: BlocBuilder( builder: (context, dashboardState) { if (dashboardState is DashboardLoading) { return const Center( child: CircularProgressIndicator(color: UnionFlowColors.amber), ); } final dashboardData = (dashboardState is DashboardLoaded) ? dashboardState.dashboardData : null; final stats = dashboardData?.stats; return SingleChildScrollView( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // En-tête Consultant AnimatedFadeIn( delay: const Duration(milliseconds: 100), child: _buildUserHeader(), ), const SizedBox(height: 24), // Stats missions (données backend réelles) AnimatedSlideIn( delay: const Duration(milliseconds: 200), child: Row( children: [ Expanded( child: UnionStatWidget( label: 'Événements', value: '${stats?.totalEvents ?? 0}', icon: Icons.work_outline, color: UnionFlowColors.amber, trend: stats?.upcomingEvents != null ? '${stats!.upcomingEvents} à venir' : null, isTrendUp: true, ), ), const SizedBox(width: 12), Expanded( child: UnionStatWidget( label: 'Organisations', value: '${stats?.totalOrganizations ?? 0}', icon: Icons.business_outlined, color: UnionFlowColors.indigo, ), ), ], ), ), const SizedBox(height: 12), AnimatedFadeIn( delay: const Duration(milliseconds: 300), child: Row( children: [ Expanded( child: UnionStatWidget( label: 'Demandes', value: '${stats?.pendingRequests ?? 0}', icon: Icons.pending_actions, color: UnionFlowColors.warning, ), ), const SizedBox(width: 12), Expanded( child: UnionStatWidget( label: 'Membres', value: '${stats?.totalMembers ?? 0}', icon: Icons.people_outline, color: UnionFlowColors.success, ), ), ], ), ), const SizedBox(height: 24), // Événements à venir (données backend) if (dashboardData != null && dashboardData.hasUpcomingEvents) ...[ AnimatedFadeIn( delay: const Duration(milliseconds: 400), child: const Text( 'Prochains Événements', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w700, color: UnionFlowColors.textPrimary, ), ), ), const SizedBox(height: 16), AnimatedSlideIn( delay: const Duration(milliseconds: 500), child: Column( children: dashboardData.upcomingEvents.take(3).map((event) => Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(14), decoration: BoxDecoration( color: UnionFlowColors.surface, borderRadius: BorderRadius.circular(12), border: Border.all(color: UnionFlowColors.border, width: 1), boxShadow: UnionFlowColors.softShadow, ), child: Row( children: [ Container( width: 48, height: 48, decoration: BoxDecoration( gradient: UnionFlowColors.warmGradient, borderRadius: BorderRadius.circular(10), ), child: const Icon( Icons.calendar_today, color: Colors.white, size: 22, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( event.title, style: const TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: UnionFlowColors.textPrimary, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), const SizedBox(height: 4), Text( event.formattedDate, style: const TextStyle( fontSize: 12, color: UnionFlowColors.textSecondary, ), ), ], ), ), ], ), ) ).toList(), ), ), const SizedBox(height: 24), ], // Répartition organisations par type (données backend) if (stats != null && stats.organizationTypeDistribution != null && stats.organizationTypeDistribution!.isNotEmpty) ...[ AnimatedFadeIn( delay: const Duration(milliseconds: 600), child: UnionPieChart( title: 'Répartition Organisations', subtitle: 'Par type', sections: _buildOrgTypeSections(stats.organizationTypeDistribution!), ), ), const SizedBox(height: 24), ], // Actions consultant AnimatedFadeIn( delay: const Duration(milliseconds: 700), child: const Text( 'Mes Outils', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w700, color: UnionFlowColors.textPrimary, ), ), ), const SizedBox(height: 16), AnimatedSlideIn( delay: const Duration(milliseconds: 700), child: Row( children: [ Expanded( child: UnionActionButton( label: 'Audits', icon: Icons.assessment, onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (_) => const ReportsPageWrapper())), backgroundColor: UnionFlowColors.unionGreen, ), ), const SizedBox(width: 12), Expanded( child: UnionActionButton( label: 'Analyses', icon: Icons.analytics, onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (_) => const ReportsPageWrapper())), backgroundColor: UnionFlowColors.indigo, ), ), const SizedBox(width: 12), Expanded( child: UnionActionButton( label: 'Rapports', icon: Icons.description, onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (_) => const ReportsPageWrapper())), backgroundColor: UnionFlowColors.gold, ), ), ], ), ), const SizedBox(height: 12), AnimatedSlideIn( delay: const Duration(milliseconds: 800), child: Row( children: [ Expanded( child: UnionActionButton( label: 'Clients', icon: Icons.people_outline, onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (_) => const MembersPageWrapper())), backgroundColor: UnionFlowColors.amber, ), ), const SizedBox(width: 12), Expanded( child: UnionActionButton( label: 'Calendrier', icon: Icons.calendar_today, onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (_) => const EventsPageWrapper())), backgroundColor: UnionFlowColors.terracotta, ), ), const SizedBox(width: 12), Expanded( child: UnionActionButton( label: 'Documents', icon: Icons.folder_outlined, onTap: () => Navigator.of(context).push(MaterialPageRoute(builder: (_) => const HelpSupportPage())), backgroundColor: UnionFlowColors.info, ), ), ], ), ), ], ), ); }, ), ), ); } PreferredSizeWidget _buildAppBar(BuildContext context) { return AppBar( backgroundColor: UnionFlowColors.surface, elevation: 0, title: Row( children: [ Container( width: 32, height: 32, decoration: BoxDecoration( gradient: LinearGradient( colors: [UnionFlowColors.amber, UnionFlowColors.gold], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(8), ), alignment: Alignment.center, child: const Text( 'C', style: TextStyle( color: Colors.white, fontWeight: FontWeight.w900, fontSize: 18, ), ), ), const SizedBox(width: 12), const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'UnionFlow', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w700, color: UnionFlowColors.textPrimary, ), ), Text( 'Consultant', style: TextStyle( fontSize: 11, fontWeight: FontWeight.w400, color: UnionFlowColors.textSecondary, ), ), ], ), ], ), iconTheme: const IconThemeData(color: UnionFlowColors.textPrimary), actions: [ UnionExportButton( onExport: (_) => Navigator.of(context).push( MaterialPageRoute(builder: (_) => const ReportsPageWrapper()), ), ), const SizedBox(width: 8), ], ); } Widget _buildUserHeader() { return Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( gradient: LinearGradient( colors: [UnionFlowColors.amber, UnionFlowColors.gold], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(16), border: const Border( top: BorderSide(color: UnionFlowColors.amber, width: 3), ), boxShadow: [ BoxShadow( color: UnionFlowColors.amber.withOpacity(0.3), blurRadius: 12, offset: const Offset(0, 4), ), ], ), child: Row( children: [ CircleAvatar( radius: 28, backgroundColor: Colors.white.withOpacity(0.3), child: const Text( 'CON', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w700, color: Colors.white, ), ), ), const SizedBox(width: 16), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Consultant Expert', style: TextStyle( fontSize: 15, fontWeight: FontWeight.w700, color: Colors.white, ), ), const SizedBox(height: 4), Text( 'Expertise & Analyses Stratégiques', style: TextStyle( fontSize: 12, color: Colors.white.withOpacity(0.9), ), ), ], ), ), Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: const Text( 'EXPERT', style: TextStyle( fontSize: 10, fontWeight: FontWeight.w800, color: UnionFlowColors.amber, letterSpacing: 0.5, ), ), ), ], ), ); } List _buildOrgTypeSections(Map distribution) { final colors = [ UnionFlowColors.unionGreen, UnionFlowColors.gold, UnionFlowColors.indigo, UnionFlowColors.amber, UnionFlowColors.terracotta, ]; final total = distribution.values.fold(0, (sum, value) => sum + value); final entries = distribution.entries.toList(); return List.generate(entries.length.clamp(0, 5), (index) { final entry = entries[index]; final percentage = total > 0 ? (entry.value / total * 100).toStringAsFixed(0) : '0'; return UnionPieChartSection.create( value: entry.value.toDouble(), color: colors[index % colors.length], title: '$percentage%\n${entry.key}', ); }); } }