diff --git a/lib/data/state/analysis_charts_visibility_notifier.dart b/lib/data/state/analysis_charts_visibility_notifier.dart index f8c6ac3..403739a 100644 --- a/lib/data/state/analysis_charts_visibility_notifier.dart +++ b/lib/data/state/analysis_charts_visibility_notifier.dart @@ -6,7 +6,6 @@ class AnalysisChartsVisibilityNotifier : super({ 'globalStats': true, 'questionsAnalysis': true, - 'globalDistribution': true, 'questionsDetailed': true, 'atRiskEmployees': true, }); diff --git a/lib/data/utils/qvst_chart_utils.dart b/lib/data/utils/qvst_chart_utils.dart index a4faefd..c181194 100644 --- a/lib/data/utils/qvst_chart_utils.dart +++ b/lib/data/utils/qvst_chart_utils.dart @@ -1,14 +1,6 @@ import 'package:flutter/material.dart'; class QvstChartUtils { - static const List globalScoreColors = [ - Color(0xFF388E3C), - Color(0xFF8BC34A), - Color(0xFF9E9E9E), - Color(0xFFF57C00), - Color(0xFFD32F2F), - ]; - static String getLabelForScore(int score, {Map? labels}) { if (labels != null && labels.containsKey(score)) { return labels[score]!; @@ -16,9 +8,30 @@ class QvstChartUtils { return 'Note $score'; } - static Color getColorForScore(int score) { + /// Returns the color for a given score, with optional inversion for reversed questions. + /// When `isReversed` is false (positive question): mapping is green → red (score 5 = green, score 1 = red). + /// When `isReversed` is true (negative question): mapping is inverted so that favorable responses stay green. + static Color getColorForScore(int score, {bool isReversed = false}) { if (score < 1 || score > 5) return Colors.grey; - return globalScoreColors[score - 1]; + + const Map positiveMapping = { + 5: Color(0xFF388E3C), // Green: Strongly agree / very positive + 4: Color(0xFF8BC34A), // Light green + 3: Color(0xFF9E9E9E), // Neutral (grey/yellow) + 2: Color(0xFFF57C00), // Orange + 1: Color(0xFFD32F2F), // Red: Strongly disagree / very negative + }; + + const Map reversedMapping = { + 5: Color(0xFFD32F2F), // Red: high score is negative in this context + 4: Color(0xFFF57C00), // Orange + 3: Color(0xFF9E9E9E), // Neutral + 2: Color(0xFF8BC34A), // Light green + 1: Color(0xFF388E3C), // Green: low score is positive in this context + }; + + final mapping = isReversed ? reversedMapping : positiveMapping; + return mapping[score] ?? Colors.grey; } static Color getSatisfactionColor(double satisfaction) { diff --git a/lib/presentation/widgets/qvst/charts/questions_selection_pie_chart.dart b/lib/presentation/widgets/qvst/charts/questions_selection_pie_chart.dart index c9b2782..a3c439c 100644 --- a/lib/presentation/widgets/qvst/charts/questions_selection_pie_chart.dart +++ b/lib/presentation/widgets/qvst/charts/questions_selection_pie_chart.dart @@ -1,12 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:syncfusion_flutter_charts/charts.dart'; import 'package:xpeapp_admin/data/entities/qvst/analysis/qvst_analysis_entity.dart'; import 'package:xpeapp_admin/data/utils/qvst_chart_utils.dart'; import 'package:xpeapp_admin/data/utils/qvst_ui_utils.dart'; import 'package:xpeapp_admin/presentation/widgets/common/collapsible_card.dart'; import 'package:xpeapp_admin/presentation/widgets/common/screenshot_button.dart'; +import 'package:xpeapp_admin/providers.dart'; -class QuestionsSelectionPieChart extends StatefulWidget { +class QuestionsSelectionPieChart extends ConsumerStatefulWidget { final List questionsAnalysis; const QuestionsSelectionPieChart({ @@ -15,12 +17,12 @@ class QuestionsSelectionPieChart extends StatefulWidget { }); @override - State createState() => + ConsumerState createState() => _QuestionsSelectionPieChartState(); } class _QuestionsSelectionPieChartState - extends State { + extends ConsumerState { static const int _maxScore = 5; final Set _selectedQuestionIds = {}; @@ -49,6 +51,7 @@ class _QuestionsSelectionPieChartState @override Widget build(BuildContext context) { + final reversedQuestions = ref.watch(reversedQuestionsProvider); final chartKey = GlobalKey(); if (widget.questionsAnalysis.isEmpty) { @@ -100,7 +103,7 @@ class _QuestionsSelectionPieChartState else RepaintBoundary( key: chartKey, - child: _buildPieChart(selectedQuestions), + child: _buildPieChart(selectedQuestions, reversedQuestions), ), ], ), @@ -145,7 +148,8 @@ class _QuestionsSelectionPieChartState ); } - Widget _buildPieChart(List selectedQuestions) { + Widget _buildPieChart(List selectedQuestions, + Map reversedQuestions) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -166,7 +170,8 @@ class _QuestionsSelectionPieChartState childAspectRatio: 1, physics: const NeverScrollableScrollPhysics(), children: selectedQuestions.map((question) { - final data = _buildChartDataForQuestion(question); + final isReversed = reversedQuestions[question.questionId] ?? false; + final data = _buildChartDataForQuestion(question, isReversed); final totalResponses = data.fold(0, (s, d) => s + d.count); return Card( @@ -275,7 +280,7 @@ class _QuestionsSelectionPieChartState } List<_PieChartData> _buildChartDataForQuestion( - QuestionAnalysisEntity question) { + QuestionAnalysisEntity question, bool isReversed) { final countsByScore = {for (var i = 1; i <= _maxScore; i++) i: 0}; final answerLabels = {}; @@ -294,14 +299,17 @@ class _QuestionsSelectionPieChartState } } - return List.generate(_maxScore, (i) { - final score = i + 1; + // Generate data sorted by descending score (5→1) so segments are displayed clockwise + final result = List.generate(_maxScore, (i) { + final score = _maxScore - i; // Trier décroissant: 5, 4, 3, 2, 1 return _PieChartData( label: QvstChartUtils.getLabelForScore(score, labels: answerLabels), count: countsByScore[score] ?? 0, - color: QvstChartUtils.getColorForScore(score), + color: QvstChartUtils.getColorForScore(score, isReversed: isReversed), ); }).where((data) => data.count > 0).toList(); + + return result; } void _toggleQuestion(String questionId) { diff --git a/test/data/state/analysis_charts_visibility_notifier_test.dart b/test/data/state/analysis_charts_visibility_notifier_test.dart index 867f7b8..e520ca8 100644 --- a/test/data/state/analysis_charts_visibility_notifier_test.dart +++ b/test/data/state/analysis_charts_visibility_notifier_test.dart @@ -13,7 +13,6 @@ void main() { expect(notifier.state, { 'globalStats': true, 'questionsAnalysis': true, - 'globalDistribution': true, 'questionsDetailed': true, 'atRiskEmployees': true, }); diff --git a/test/data/utils/qvst_chart_utils_test.dart b/test/data/utils/qvst_chart_utils_test.dart new file mode 100644 index 0000000..4da9f37 --- /dev/null +++ b/test/data/utils/qvst_chart_utils_test.dart @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:xpeapp_admin/data/utils/qvst_chart_utils.dart'; + +void main() { + group('QvstChartUtils.getColorForScore', () { + test('returns green for score 5 when not reversed', () { + final color = QvstChartUtils.getColorForScore(5, isReversed: false); + expect(color, equals(const Color(0xFF388E3C))); + }); + + test('returns red for score 1 when not reversed', () { + final color = QvstChartUtils.getColorForScore(1, isReversed: false); + expect(color, equals(const Color(0xFFD32F2F))); + }); + + test('returns inverted mapping when reversed=true (score 1 -> green)', () { + final color = QvstChartUtils.getColorForScore(1, isReversed: true); + expect(color, equals(const Color(0xFF388E3C))); + }); + + test('returns inverted mapping when reversed=true (score 5 -> red)', () { + final color = QvstChartUtils.getColorForScore(5, isReversed: true); + expect(color, equals(const Color(0xFFD32F2F))); + }); + + test('out-of-range returns grey', () { + final colorLow = QvstChartUtils.getColorForScore(0); + final colorHigh = QvstChartUtils.getColorForScore(6); + expect(colorLow, equals(Colors.grey)); + expect(colorHigh, equals(Colors.grey)); + }); + }); +}