Skip to content

Projet #243

@dada566

Description

@dada566

import 'package:flutter/material.dart';
import 'dart:math' as math;

class AnalysesPage extends StatefulWidget {
const AnalysesPage({super.key});

@OverRide
State createState() => _AnalysesPageState();
}

class _AnalysesPageState extends State with TickerProviderStateMixin {
late AnimationController _gradientController;
late AnimationController _cardAnimationController;
late AnimationController _chartAnimationController;
late AnimationController _tableAnimationController;
late AnimationController _kpiAnimationController;

late Animation _cardSlideAnimation;
late Animation _chartScaleAnimation;
late Animation _tableOpacityAnimation;
late Animation _kpiCounterAnimation;

String _selectedPeriod = 'Année en cours';
String _selectedAnalysisType = 'Vue d'ensemble';
String _selectedSector = '';

final List _periods = ['Année en cours', 'Trimestre', 'Semestre', 'Législature'];
final List _analysisTypes = ['Vue d'ensemble', 'Efficacité législative', 'Participation', 'Thématiques', 'Tendances'];

@OverRide
void initState() {
super.initState();

_gradientController = AnimationController(
  duration: const Duration(seconds: 8),
  vsync: this,
)..repeat();

_cardAnimationController = AnimationController(
  duration: const Duration(milliseconds: 1200),
  vsync: this,
);

_chartAnimationController = AnimationController(
  duration: const Duration(milliseconds: 1800),
  vsync: this,
);

_tableAnimationController = AnimationController(
  duration: const Duration(milliseconds: 900),
  vsync: this,
);

_kpiAnimationController = AnimationController(
  duration: const Duration(milliseconds: 2000),
  vsync: this,
);

_setupAnimations();

WidgetsBinding.instance.addPostFrameCallback((_) {
  _cardAnimationController.forward();
  _chartAnimationController.forward();
  _tableAnimationController.forward();
  _kpiAnimationController.forward();
});

}

void _setupAnimations() {
_cardSlideAnimation = Tween(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _cardAnimationController,
curve: Curves.easeOutCubic,
),
);

_chartScaleAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
  CurvedAnimation(
    parent: _chartAnimationController,
    curve: Curves.elasticOut,
  ),
);

_tableOpacityAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
  CurvedAnimation(
    parent: _tableAnimationController,
    curve: Curves.easeInOut,
  ),
);

_kpiCounterAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(
  CurvedAnimation(
    parent: _kpiAnimationController,
    curve: Curves.easeOutCubic,
  ),
);

}

@OverRide
void dispose() {
_gradientController.dispose();
_cardAnimationController.dispose();
_chartAnimationController.dispose();
_tableAnimationController.dispose();
_kpiAnimationController.dispose();
super.dispose();
}

void _showSectorDetails(String sector, double value, Color color) {
final isDark = Theme.of(context).brightness == Brightness.dark;

showDialog(
  context: context,
  builder: (BuildContext context) {
    return Dialog(
      backgroundColor: isDark ? const Color(0xFF1E1E48) : Colors.white,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
      child: Container(
        width: 400,
        padding: const EdgeInsets.all(24),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Row(
              children: [
                Container(
                  padding: const EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    color: color.withOpacity(0.1),
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: Icon(Icons.analytics, color: color, size: 24),
                ),
                const SizedBox(width: 16),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        'Analyse - $sector',
                        style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                          color: isDark ? Colors.white : Colors.black,
                        ),
                      ),
                      Text(
                        'Efficacité: ${(value * 100).toInt()}%',
                        style: TextStyle(
                          fontSize: 14,
                          color: color,
                          fontWeight: FontWeight.w600,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
            const SizedBox(height: 20),
            
            _buildDetailRow('Projets déposés', '${(value * 45).toInt()}', Icons.description),
            _buildDetailRow('Projets adoptés', '${(value * 32).toInt()}', Icons.check_circle),
            _buildDetailRow('Temps moyen', '${(value * 6.5).toStringAsFixed(1)} jours', Icons.schedule),
            _buildDetailRow('Amendements', '${(value * 156).toInt()}', Icons.edit),
            
            const SizedBox(height: 24),
            Row(
              children: [
                Expanded(
                  child: ElevatedButton(
                    onPressed: () => Navigator.pop(context),
                    style: ElevatedButton.styleFrom(
                      backgroundColor: Colors.grey[300],
                      foregroundColor: Colors.black,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(12),
                      ),
                    ),
                    child: const Text('Fermer'),
                  ),
                ),
                const SizedBox(width: 12),
                Expanded(
                  child: ElevatedButton(
                    onPressed: () {
                      Navigator.pop(context);
                      setState(() {
                        _selectedSector = sector;
                      });
                    },
                    style: ElevatedButton.styleFrom(
                      backgroundColor: color,
                      foregroundColor: Colors.white,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(12),
                      ),
                    ),
                    child: const Text('Détails complets'),
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  },
);

}

Widget _buildDetailRow(String label, String value, IconData icon) {
final isDark = Theme.of(context).brightness == Brightness.dark;

return Padding(
  padding: const EdgeInsets.symmetric(vertical: 8),
  child: Row(
    children: [
      Icon(icon, size: 20, color: isDark ? Colors.white70 : Colors.grey[600]),
      const SizedBox(width: 12),
      Expanded(
        child: Text(
          label,
          style: TextStyle(
            fontSize: 14,
            color: isDark ? Colors.white70 : Colors.grey[700],
          ),
        ),
      ),
      Text(
        value,
        style: TextStyle(
          fontSize: 14,
          fontWeight: FontWeight.bold,
          color: isDark ? Colors.white : Colors.black,
        ),
      ),
    ],
  ),
);

}

void _showKpiDetails(String title, String value, String description) {
final isDark = Theme.of(context).brightness == Brightness.dark;

showDialog(
  context: context,
  builder: (BuildContext context) {
    return Dialog(
      backgroundColor: isDark ? const Color(0xFF1E1E48) : Colors.white,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
      child: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(
              title,
              style: TextStyle(
                fontSize: 20,
                fontWeight: FontWeight.bold,
                color: isDark ? Colors.white : Colors.black,
              ),
            ),
            const SizedBox(height: 16),
            Text(
              value,
              style: const TextStyle(
                fontSize: 32,
                fontWeight: FontWeight.bold,
                color: Color(0xFF6366F1),
              ),
            ),
            const SizedBox(height: 12),
            Text(
              description,
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize: 16,
                color: isDark ? Colors.white70 : Colors.grey[600],
              ),
            ),
            const SizedBox(height: 24),
            ElevatedButton(
              onPressed: () => Navigator.pop(context),
              style: ElevatedButton.styleFrom(
                backgroundColor: const Color(0xFF6366F1),
                foregroundColor: Colors.white,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(12),
                ),
              ),
              child: const Text('Fermer'),
            ),
          ],
        ),
      ),
    );
  },
);

}

Widget _buildKpiCard(String title, String value, String subtitle, IconData icon, Color color, double targetValue, int index) {
final isDark = Theme.of(context).brightness == Brightness.dark;

return AnimatedBuilder(
  animation: _kpiAnimationController,
  builder: (context, child) {
    final animationDelay = index * 0.2;
    final delayedAnimation = math.max(0.0, _kpiCounterAnimation.value - animationDelay);
    final displayValue = (targetValue * delayedAnimation).toInt();
    
    return Transform.translate(
      offset: Offset(0, 30 * (1 - delayedAnimation.clamp(0.0, 1.0))),
      child: Opacity(
        opacity: delayedAnimation.clamp(0.0, 1.0),
        child: MouseRegion(
          cursor: SystemMouseCursors.click,
          child: GestureDetector(
            onTap: () => _showKpiDetails(title, value, subtitle),
            child: Container(
              padding: const EdgeInsets.all(20),
              decoration: BoxDecoration(
                color: isDark ? const Color(0xFF1E1E48) : Colors.white,
                borderRadius: BorderRadius.circular(16),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withOpacity(0.1),
                    blurRadius: 12,
                    offset: const Offset(0, 4),
                  ),
                ],
                border: Border.all(
                  color: color.withOpacity(0.3),
                  width: 1.5,
                ),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Row(
                    children: [
                      Container(
                        padding: const EdgeInsets.all(12),
                        decoration: BoxDecoration(
                          color: color.withOpacity(0.1),
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: Icon(icon, color: color, size: 24),
                      ),
                      const Spacer(),
                      Container(
                        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
                        decoration: BoxDecoration(
                          color: color.withOpacity(0.1),
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: Text(
                          '+${(displayValue * 0.12).toInt()}%',
                          style: TextStyle(
                            fontSize: 12,
                            fontWeight: FontWeight.bold,
                            color: color,
                          ),
                        ),
                      ),
                    ],
                  ),
                  const SizedBox(height: 16),
                  Text(
                    displayValue.toString(),
                    style: TextStyle(
                      fontSize: 28,
                      fontWeight: FontWeight.bold,
                      color: color,
                    ),
                  ),
                  const SizedBox(height: 4),
                  Text(
                    title,
                    style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.w600,
                      color: isDark ? Colors.white : Colors.black,
                    ),
                  ),
                  Text(
                    subtitle,
                    style: TextStyle(
                      fontSize: 12,
                      color: isDark ? Colors.white60 : Colors.grey[600],
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  },
);

}

Widget _buildAnalysisChart() {
final isDark = Theme.of(context).brightness == Brightness.dark;

return AnimatedBuilder(
  animation: _chartAnimationController,
  builder: (context, child) {
    return Transform.scale(
      scale: _chartScaleAnimation.value.clamp(0.0, 1.0),
      child: Container(
        padding: const EdgeInsets.all(20),
        decoration: BoxDecoration(
          color: isDark ? const Color(0xFF1E1E48) : Colors.white,
          borderRadius: BorderRadius.circular(16),
          boxShadow: [
            BoxShadow(
              color: Colors.black.withOpacity(0.1),
              blurRadius: 8,
              offset: const Offset(0, 4),
            ),
          ],
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Text(
                  'Efficacité législative par secteur',
                  style: TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                    color: isDark ? Colors.white : Colors.black,
                  ),
                ),
                const Spacer(),
                Container(
                  padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
                  decoration: BoxDecoration(
                    color: const Color(0xFF6366F1).withOpacity(0.1),
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: const Text(
                    'Données en temps réel',
                    style: TextStyle(
                      fontSize: 12,
                      color: Color(0xFF6366F1),
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                ),
              ],
            ),
            const SizedBox(height: 20),
            Expanded(
              child: Row(
                children: [
                  Expanded(
                    flex: 2,
                    child: Column(
                      children: [
                        _buildClickableHorizontalBar('Économie', 0.85, const Color(0xFF6366F1)),
                        _buildClickableHorizontalBar('Justice', 0.72, const Color(0xFFF59E0B)),
                        _buildClickableHorizontalBar('Infrastructure', 0.65, const Color(0xFF10B981)),
                        _buildClickableHorizontalBar('Social', 0.58, const Color(0xFFEC4899)),
                        _buildClickableHorizontalBar('Éducation', 0.45, const Color(0xFF8B5CF6)),
                        _buildClickableHorizontalBar('Santé', 0.38, const Color(0xFF06B6D4)),
                      ],
                    ),
                  ),
                  const SizedBox(width: 20),
                  Expanded(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [
                        _buildClickableCircularIndicator('Taux adoption', 0.73, const Color(0xFF10B981)),
                        _buildClickableCircularIndicator('Temps moyen', 0.45, const Color(0xFFF59E0B)),
                        _buildClickableCircularIndicator('Qualité débats', 0.82, const Color(0xFF6366F1)),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  },
);

}

Widget _buildClickableHorizontalBar(String label, double value, Color color) {
final isDark = Theme.of(context).brightness == Brightness.dark;

return AnimatedBuilder(
  animation: _chartAnimationController,
  builder: (context, child) {
    final animatedValue = (value * _chartScaleAnimation.value).clamp(0.0, 1.0);
    
    return MouseRegion(
      cursor: SystemMouseCursors.click,
      child: GestureDetector(
        onTap: () => _showSectorDetails(label, value, color),
        child: Container(
          margin: const EdgeInsets.symmetric(vertical: 4),
          padding: const EdgeInsets.all(8),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(8),
            color: _selectedSector == label 
                ? color.withOpacity(0.1) 
                : Colors.transparent,
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(
                    label,
                    style: TextStyle(
                      fontSize: 14,
                      fontWeight: _selectedSector == label ? FontWeight.bold : FontWeight.w600,
                      color: _selectedSector == label 
                          ? color 
                          : (isDark ? Colors.white : Colors.black),
                    ),
                  ),
                  Text(
                    '${(value * 100).toInt()}%',
                    style: TextStyle(
                      fontSize: 14,
                      fontWeight: FontWeight.bold,
                      color: color,
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 6),
              Container(
                height: 8,
                decoration: BoxDecoration(
                  color: isDark ? Colors.grey[700] : Colors.grey[200],
                  borderRadius: BorderRadius.circular(4),
                ),
                child: FractionallySizedBox(
                  alignment: Alignment.centerLeft,
                  widthFactor: animatedValue,
                  child: Container(
                    decoration: BoxDecoration(
                      gradient: LinearGradient(
                        colors: [color.withOpacity(0.8), color],
                      ),
                      borderRadius: BorderRadius.circular(4),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  },
);

}

Widget _buildClickableCircularIndicator(String label, double value, Color color) {
return AnimatedBuilder(
animation: _chartAnimationController,
builder: (context, child) {
final animatedValue = (value * _chartScaleAnimation.value).clamp(0.0, 1.0);

    return MouseRegion(
      cursor: SystemMouseCursors.click,
      child: GestureDetector(
        onTap: () => _showKpiDetails(label, '${(value * 100).toInt()}%', 'Métrique de performance législative'),
        child: Column(
          children: [
            SizedBox(
              width: 60,
              height: 60,
              child: Stack(
                alignment: Alignment.center,
                children: [
                  CircularProgressIndicator(
                    value: animatedValue,
                    strokeWidth: 6,
                    backgroundColor: color.withOpacity(0.2),
                    color: color,
                  ),
                  Text(
                    '${(value * 100).toInt()}%',
                    style: TextStyle(
                      fontSize: 12,
                      fontWeight: FontWeight.bold,
                      color: color,
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: 8),
            Text(
              label,
              style: const TextStyle(
                fontSize: 10,
                fontWeight: FontWeight.w500,
              ),
              textAlign: TextAlign.center,
            ),
          ],
        ),
      ),
    );
  },
);

}

Widget _buildTrendAnalysisTable() {
final isDark = Theme.of(context).brightness == Brightness.dark;

return AnimatedBuilder(
  animation: _tableAnimationController,
  builder: (context, child) {
    return Opacity(
      opacity: _tableOpacityAnimation.value,
      child: Container(
        padding: const EdgeInsets.all(20),
        decoration: BoxDecoration(
          color: isDark ? const Color(0xFF1E1E48) : Colors.white,
          borderRadius: BorderRadius.circular(16),
          boxShadow: [
            BoxShadow(
              color: Colors.black.withOpacity(0.1),
              blurRadius: 8,
              offset: const Offset(0, 4),
            ),
          ],
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              'Analyse des tendances parlementaires',
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
                color: isDark ? Colors.white : Colors.black,
              ),
            ),
            const SizedBox(height: 16),
            Expanded(
              child: ListView(
                children: [
                  _buildClickableAnalysisRow('Projets déposés', '342', '+18%', Colors.blue),
                  _buildClickableAnalysisRow('Taux d\'adoption', '73%', '+5%', const Color(0xFF10B981)),
                  _buildClickableAnalysisRow('Amendements proposés', '1,247', '+32%', const Color(0xFFF59E0B)),
                  _buildClickableAnalysisRow('Temps moyen débat', '4.2h', '-12%', Colors.red),
                  _buildClickableAnalysisRow('Participation moyenne', '94%', '+3%', const Color(0xFF8B5CF6)),
                  _buildClickableAnalysisRow('Urgences traitées', '23', '+41%', const Color(0xFFEC4899)),
                  _buildClickableAnalysisRow('Questions orales', '156', '+25%', const Color(0xFF06B6D4)),
                  _buildClickableAnalysisRow('Interpellations', '78', '+12%', const Color(0xFF84CC16)),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  },
);

}

Widget _buildClickableAnalysisRow(String metric, String value, String change, Color color) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final isPositive = change.startsWith('+');

return MouseRegion(
  cursor: SystemMouseCursors.click,
  child: GestureDetector(
    onTap: () => _showKpiDetails(metric, value, 'Évolution par rapport à la période précédente: $change'),
    child: Container(
      padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8),
      margin: const EdgeInsets.symmetric(vertical: 2),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(8),
        color: Colors.transparent,
      ),
      child: Row(
        children: [
          Expanded(
            flex: 3,
            child: Text(
              metric,
              style: TextStyle(
                fontSize: 14,
                color: isDark ? Colors.white70 : Colors.black87,
              ),
            ),
          ),
          Expanded(
            child: Text(
              value,
              style: TextStyle(
                fontSize: 16,
                fontWeight: FontWeight.bold,
                color: isDark ? Colors.white : Colors.black,
              ),
              textAlign: TextAlign.center,
            ),
          ),
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
            decoration: BoxDecoration(
              color: (isPositive ? const Color(0xFF10B981) : Colors.red).withOpacity(0.1),
              borderRadius: BorderRadius.circular(12),
            ),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                Icon(
                  isPositive ? Icons.trending_up : Icons.trending_down,
                  size: 14,
                  color: isPositive ? const Color(0xFF10B981) : Colors.red,
                ),
                const SizedBox(width: 4),
                Text(
                  change,
                  style: TextStyle(
                    fontSize: 12,
                    fontWeight: FontWeight.bold,
                    color: isPositive ? const Color(0xFF10B981) : Colors.red,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    ),
  ),
);

}

Widget _buildThematicAnalysis() {
final isDark = Theme.of(context).brightness == Brightness.dark;

return AnimatedBuilder(
  animation: _cardAnimationController,
  builder: (context, child) {
    return Transform.translate(
      offset: Offset(0, 20 * (1 - _cardSlideAnimation.value)),
      child: Opacity(
        opacity: _cardSlideAnimation.value,
        child: Container(
          padding: const EdgeInsets.all(20),
          decoration: BoxDecoration(
            color: isDark ? const Color(0xFF1E1E48) : Colors.white,
            borderRadius: BorderRadius.circular(16),
            boxShadow: [
              BoxShadow(
                color: Colors.black.withOpacity(0.1),
                blurRadius: 8,
                offset: const Offset(0, 4),
              ),
            ],
          ),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                'Répartition thématique des débats',
                style: TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                  color: isDark ? Colors.white : Colors.black,
                ),
              ),
              const SizedBox(height: 20),
              Expanded(
                child: SingleChildScrollView(
                  child: Wrap(
                    spacing: 12,
                    runSpacing: 12,
                    children: [
                      _buildClickableThemeChip('Économie', 32, const Color(0xFF6366F1)),
                      _buildClickableThemeChip('Infrastructure', 28, const Color(0xFF10B981)),
                      _buildClickableThemeChip('Justice', 24, const Color(0xFFF59E0B)),
                      _buildClickableThemeChip('Social', 18, const Color(0xFFEC4899)),
                      _buildClickableThemeChip('Éducation', 15, const Color(0xFF8B5CF6)),
                      _buildClickableThemeChip('Santé', 12, const Color(0xFF06B6D4)),
                      _buildClickableThemeChip('Environnement', 8, const Color(0xFF84CC16)),
                      _buildClickableThemeChip('Culture', 5, const Color(0xFFF97316)),
                    ],
                  ),
                ),
              ),
              const SizedBox(height: 20),
              MouseRegion(
                cursor: SystemMouseCursors.click,
                child: GestureDetector(
                  onTap: () => _showKpiDetails(
                    'Analyse prédictive IA',
                    '85%',
                    'Probabilité d\'adoption des projets économiques dans les 6 prochaines semaines',
                  ),
                  child: Container(
                    padding: const EdgeInsets.all(16),
                    decoration: BoxDecoration(
                      color: const Color(0xFF6366F1).withOpacity(0.1),
                      borderRadius: BorderRadius.circular(12),
                      border: Border.all(
                        color: const Color(0xFF6366F1).withOpacity(0.3),
                      ),
                    ),
                    child: Row(
                      children: [
                        Icon(
                          Icons.insights,
                          color: const Color(0xFF6366F1),
                          size: 24,
                        ),
                        const SizedBox(width: 12),
                        Expanded(
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                'Analyse prédictive',
                                style: TextStyle(
                                  fontSize: 14,
                                  fontWeight: FontWeight.bold,
                                  color: isDark ? Colors.white : Colors.black,
                                ),
                              ),
                              Text(
                                'Les projets économiques ont 85% de probabilité d\'adoption dans les 6 prochaines semaines',
                                style: TextStyle(
                                  fontSize: 12,
                                  color: isDark ? Colors.white60 : Colors.grey[600],
                                ),
                              ),
                            ],
                          ),
                        ),
                        Icon(
                          Icons.arrow_forward_ios,
                          color: const Color(0xFF6366F1),
                          size: 16,
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  },
);

}

Widget _buildClickableThemeChip(String theme, int count, Color color) {
return AnimatedBuilder(
animation: _cardAnimationController,
builder: (context, child) {
final animatedCount = (count * _cardSlideAnimation.value).toInt();

    return MouseRegion(
      cursor: SystemMouseCursors.click,
      child: GestureDetector(
        onTap: () => _showSectorDetails(theme, count / 40.0, color),
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
          decoration: BoxDecoration(
            color: color.withOpacity(0.1),
            borderRadius: BorderRadius.circular(16),
            border: Border.all(color: color.withOpacity(0.3)),
          ),
          child: Row(
            mainAxisSize: MainAxisSize.min,
            children: [
              Container(
                width: 8,
                height: 8,
                decoration: BoxDecoration(
                  color: color,
                  shape: BoxShape.circle,
                ),
              ),
              const SizedBox(width: 8),
              Text(
                theme,
                style: TextStyle(
                  fontSize: 12,
                  fontWeight: FontWeight.w600,
                  color: color,
                ),
              ),
              const SizedBox(width: 4),
              Text(
                '($animatedCount)',
                style: TextStyle(
                  fontSize: 12,
                  color: color.withOpacity(0.7),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  },
);

}

@OverRide
Widget build(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;

return AnimatedBuilder(
  animation: _gradientController,
  builder: (context, child) {
    return Container(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
          stops: const [0.0, 0.5, 1.0],
          colors: [
            Color.lerp(const Color.fromARGB(229, 45, 55, 72), const Color(0xFF1A1A4F), 
              0.5 + 0.1 * math.sin(_gradientController.value * math.pi))!,
            const Color.fromARGB(255, 19, 16, 52),
            Color.lerp(const Color.fromARGB(255, 18, 15, 51), const Color.fromARGB(75, 99, 102, 241), 
              0.5 + 0.1 * math.cos(_gradientController.value * math.pi))!,
          ],
        ),
      ),
      child: Scaffold(
        backgroundColor: Colors.transparent,
        body: SafeArea(
          child: Padding(
            padding: const EdgeInsets.all(20),
            child: Column(
              children: [
                // Filtres de période et type d'analyse
                Row(
                  children: [
                    Expanded(
                      child: Container(
                        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                        decoration: BoxDecoration(
                          color: isDark ? const Color(0xFF1E1E48) : Colors.white,
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: DropdownButtonHideUnderline(
                          child: DropdownButton<String>(
                            value: _selectedPeriod,
                            items: _periods.map((period) => 
                              DropdownMenuItem(value: period, child: Text(period))
                            ).toList(),
                            onChanged: (value) => setState(() => _selectedPeriod = value!),
                            style: TextStyle(
                              color: isDark ? Colors.white : Colors.black,
                              fontSize: 14,
                            ),
                            dropdownColor: isDark ? const Color(0xFF1E1E48) : Colors.white,
                            icon: const Icon(Icons.keyboard_arrow_down),
                          ),
                        ),
                      ),
                    ),
                    const SizedBox(width: 12),
                    Expanded(
                      child: Container(
                        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
                        decoration: BoxDecoration(
                          color: isDark ? const Color(0xFF1E1E48) : Colors.white,
                          borderRadius: BorderRadius.circular(12),
                        ),
                        child: DropdownButtonHideUnderline(
                          child: DropdownButton<String>(
                            value: _selectedAnalysisType,
                            items: _analysisTypes.map((type) => 
                              DropdownMenuItem(value: type, child: Text(type))
                            ).toList(),
                            onChanged: (value) => setState(() => _selectedAnalysisType = value!),
                            style: TextStyle(
                              color: isDark ? Colors.white : Colors.black,
                              fontSize: 14,
                            ),
                            dropdownColor: isDark ? const Color(0xFF1E1E48) : Colors.white,
                            icon: const Icon(Icons.keyboard_arrow_down),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
                
                const SizedBox(height: 20),
                
                // Indicateurs KPI principaux - Hauteur fixe
                SizedBox(
                  height: 150,
                  child: Row(
                    children: [
                      Expanded(child: _buildKpiCard('Projets analysés', '342', 'Cette période', Icons.analytics, const Color(0xFF6366F1), 342, 0)),
                      const SizedBox(width: 12),
                      Expanded(child: _buildKpiCard('Taux de réussite', '73%', 'Adoption moyenne', Icons.trending_up, const Color(0xFF10B981), 73, 1)),
                      const SizedBox(width: 12),
                      Expanded(child: _buildKpiCard('Temps moyen', '4.2j', 'Traitement projet', Icons.schedule, const Color(0xFFF59E0B), 42, 2)),
                      const SizedBox(width: 12),
                      Expanded(child: _buildKpiCard('Impact score', '8.7/10', 'Qualité législative', Icons.star, const Color(0xFFEC4899), 87, 3)),
                    ],
                  ),
                ),
                
                const SizedBox(height: 20),
                
                // Contenu principal - CORRECTION PRINCIPALE
                Expanded(
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      // Colonne gauche - Graphiques avec contenu scrollable
                      Expanded(
                        flex: 2,
                        child: Column(
                          children: [
                            // Graphique d'analyse - Hauteur flexible
                            Expanded(
                              flex: 3,
                              child: _buildAnalysisChart(),
                            ),
                            const SizedBox(height: 20),
                            // Analyse thématique - Hauteur flexible
                            Expanded(
                              flex: 2,
                              child: _buildThematicAnalysis(),
                            ),
                          ],
                        ),
                      ),
                      
                      const SizedBox(width: 20),
                      
                      // Colonne droite - Tableau d'analyse
                      Expanded(
                        child: _buildTrendAnalysisTable(),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  },
);

}
}...The overflowing RenderFlex has an orientation of Axis.vertical.
The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be
seen. If the content is legitimately bigger than the available space, consider clipping it with a
ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
like a ListView.
The specific RenderFlex in question is: RenderFlex#6ab92 relayoutBoundary=up24 OVERFLOWING:
creator: Column ← Expanded ← Row ← Expanded ← Column ← Padding ← DecoratedBox ← Container ←
Transform ← AnimatedBuilder ← SizedBox ← Column ← ⋯
parentData: offset=Offset(0.0, 0.0); flex=2; fit=FlexFit.tight (can use size)
constraints: BoxConstraints(w=491.6, 0.0<=h<=111.0)
size: Size(491.6, 111.0)
direction: vertical
mainAxisAlignment: start
mainAxisSize: max
crossAxisAlignment: center
verticalDirection: down
spacing: 0.0
◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤
════════════════════════════════════════════════════════════════════════════════════════════════════
Another exception was thrown: A RenderFlex overflowed by 135 pixels on the bottom.
Another exception was thrown: A RenderFlex overflowed by 59 pixels on the bottom.

Performing hot restart... 708ms
Restarted application in 709ms.
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
The following assertion was thrown during layout:
A RenderFlex overflowed by 205 pixels on the bottom.

The relevant error-causing widget was:
Column Column:file:///C:/Users/Dave_Yawenda/mrp/lib/pages/analyses_page.dart:463:32

To inspect this widget in Flutter DevTools, visit:
http://127.0.0.1:9101/#/inspector?uri=http%3A%2F%2F127.0.0.1%3A52158%2Fg00992TQjgs%3D&inspectorRef=inspector-0

The overflowing RenderFlex has an orientation of Axis.vertical.
The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be
seen. If the content is legitimately bigger than the available space, consider clipping it with a
ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
like a ListView.
The specific RenderFlex in question is: RenderFlex#6ecf4 relayoutBoundary=up25 OVERFLOWING:
creator: Column ← Expanded ← Row ← Expanded ← Column ← Padding ← DecoratedBox ← Container ←
Transform ← AnimatedBuilder ← SizedBox ← Column ← ⋯
parentData: offset=Offset(0.0, 0.0); flex=2; fit=FlexFit.tight (can use size)
constraints: BoxConstraints(w=491.6, 0.0<=h<=143.0)
size: Size(491.6, 143.0)
direction: vertical
mainAxisAlignment: start
mainAxisSize: max
crossAxisAlignment: center
verticalDirection: down
spacing: 0.0
◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤
════════════════════════════════════════════════════════════════════════════════════════════════════
Another exception was thrown: A RenderFlex overflowed by 103 pixels on the bottom.
Another exception was thrown: A RenderFlex overflowed by 22 pixels on the bottom.
Another exception was thrown: A RenderFlex overflowed by 41 pixels on the bottom.
Another exception was thrown: A RenderFlex overflowed by 41 pixels on the bottom.
Another exception was thrown: A RenderFlex overflowed by 41 pixels on the bottom.
Another exception was thrown: A RenderFlex overflowed by 41 pixels on the bottom.

Performing hot restart... 1,015ms
Restarted application in 1,017ms.
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
The following assertion was thrown during layout:
A RenderFlex overflowed by 41 pixels on the bottom.

The relevant error-causing widget was:
Column Column:file:///C:/Users/Dave_Yawenda/mrp/lib/pages/analyses_page.dart:338:26

To inspect this widget in Flutter DevTools, visit:
http://127.0.0.1:9101/#/inspector?uri=http%3A%2F%2F127.0.0.1%3A52158%2Fg00992TQjgs%3D&inspectorRef=inspector-0

The overflowing RenderFlex has an orientation of Axis.vertical.
The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be
seen. If the content is legitimately bigger than the available space, consider clipping it with a
ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
like a ListView.
The specific RenderFlex in question is: RenderFlex#5bb74 relayoutBoundary=up13 OVERFLOWING:
creator: Column ← Padding ← DecoratedBox ← Container ← Listener ← _GestureSemantics ←
RawGestureDetector ← GestureDetector ← MouseRegion ← Opacity ← Transform ← AnimatedBuilder ← ⋯
parentData: offset=Offset(21.5, 21.5) (can use size)
constraints: BoxConstraints(w=252.0, 0.0<=h<=107.0)
size: Size(252.0, 107.0)
direction: vertical
mainAxisAlignment: start
mainAxisSize: max
crossAxisAlignment: start
textDirection: ltr
verticalDirection: down
spacing: 0.0
◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤
════════════════════════════════════════════════════════════════════════════════════════════════════
Another exception was thrown: A RenderFlex overflowed by 217 pixels on the bottom.
Another exception was thrown: A RenderFlex overflowed by 115 pixels on the bottom.
Another exception was thrown: A RenderFlex overflowed by 30 pixels on the bottom.
Another exception was thrown: A RenderFlex overflowed by 41 pixels on the bottom.
Another exception was thrown: A RenderFlex overflowed by 41 pixels on the bottom.
Another exception was thrown: A RenderFlex overflowed by 41 pixels on the bottom....Resous ce problème

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions