diff --git a/app/lib/screens/study/report/sections/average_section_widget.dart b/app/lib/screens/study/report/sections/average_section_widget.dart index fd895ad0c..e6fe56a26 100644 --- a/app/lib/screens/study/report/sections/average_section_widget.dart +++ b/app/lib/screens/study/report/sections/average_section_widget.dart @@ -72,7 +72,14 @@ class AverageSectionWidget extends ReportSectionWidget { section, ), const SizedBox(height: 8), - const GaugesWidget(), + GaugesWidget( + valuesInterventionA, + valuesInterventionB, + nameInterventionA, + nameInterventionB, + subject, + section, + ), const SizedBox(height: 8), getLegend(context, data), const SizedBox(height: 8), diff --git a/app/lib/screens/study/report/sections/results_gauge.dart b/app/lib/screens/study/report/sections/results_gauge.dart index adcccc8c3..e0e19a61d 100644 --- a/app/lib/screens/study/report/sections/results_gauge.dart +++ b/app/lib/screens/study/report/sections/results_gauge.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; +import 'package:gauge_indicator/gauge_indicator.dart'; +import 'package:statistics/statistics.dart'; import 'package:studyu_app/screens/study/report/sections/average_section_widget.dart'; -import 'package:syncfusion_flutter_gauges/gauges.dart'; class GaugeTitleWidget extends AverageSectionWidget { const GaugeTitleWidget( @@ -14,15 +15,28 @@ class GaugeTitleWidget extends AverageSectionWidget { return Center( child: Text( 'Average ${section.title ?? ''}', - style: const TextStyle(fontSize: 16, color: Colors.blueAccent), + style: const TextStyle(fontSize: 16, color: Colors.black87), ), ); } } -// Two gauges -class GaugesWidget extends StatelessWidget { - const GaugesWidget({super.key}); +class GaugesWidget extends AverageSectionWidget { + final String nameInterventionA; + final String nameInterventionB; + final num meanInterventionA; + final num meanInterventionB; + + GaugesWidget( + List valuesInterventionA, + List valuesInterventionB, + this.nameInterventionA, + this.nameInterventionB, + super.subject, + super.section, { + super.key, + }) : meanInterventionA = valuesInterventionA.mean, + meanInterventionB = valuesInterventionB.mean; @override Widget build(BuildContext context) { @@ -31,24 +45,40 @@ class GaugesWidget extends StatelessWidget { Expanded( child: Column( children: [ - SizedBox( - width: 140, - height: 140, - child: createGauge(0, 10, 10, 5), // min, max, steps, value + Container( + padding: const EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(12.0), + ), + child: SizedBox( + width: 160, + height: 160, + child: createGauge(0, 10, meanInterventionA, + nameInterventionA), // min, max, value + ), ), - const Text('With Tea', style: TextStyle(fontSize: 14)), ], ), ), Expanded( child: Column( children: [ - SizedBox( - width: 140, - height: 140, - child: createGauge(0, 10, 10, 7.5), // min, max, steps, value + Container( + padding: const EdgeInsets.all(8.0), + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey), + borderRadius: BorderRadius.circular(12.0), + ), + child: SizedBox( + width: 160, + height: 160, + child: createGauge(0, 10, meanInterventionB, + nameInterventionB), // min, max, value + ), ), - const Text('Without Tea', style: TextStyle(fontSize: 14)), ], ), ), @@ -56,73 +86,91 @@ class GaugesWidget extends StatelessWidget { ); } - // Create gauge with min and max values, steps to switch colors, value to point at - Widget createGauge(double min, double max, int steps, double value) { - // List of colors - final List colors = [ - Colors.red[900]!, - Colors.red[700]!, - Colors.red[500]!, - Colors.orange[900]!, - Colors.orange[700]!, - Colors.yellow[700]!, - Colors.yellow[500]!, - Colors.green[300]!, - Colors.green[500]!, - Colors.green[700]!, - ]; + Widget createGauge( + double min, double max, num value, String nameIntervention) { + const Color gaugeBackgroundColor = Color(0xFFDFE2EC); - // Create gauge ranges based on steps and the color list - List createRanges() { - final double stepValue = (max - min) / steps; - return List.generate(steps, (index) { - final double start = min + (index * stepValue); - final double end = start + stepValue; - return GaugeRange( - startValue: start, - endValue: end, - color: colors[index], - ); - }); - } - - return SfRadialGauge( - axes: [ - RadialAxis( - minimum: min, - maximum: max, - pointers: [ - NeedlePointer( - value: value, - needleColor: Colors.blue, - needleEndWidth: 7, + return Stack( + alignment: Alignment.center, + children: [ + AnimatedRadialGauge( + duration: const Duration(seconds: 1), + curve: Curves.elasticOut, + radius: 100, + value: value.toDouble(), + axis: GaugeAxis( + min: min, + max: max, + degrees: 240, // Set to 240 degrees for a 3/4 circular gauge + style: const GaugeAxisStyle( + background: gaugeBackgroundColor, + segmentSpacing: 4, + ), + pointer: const GaugePointer.needle( + width: 10, + height: 50, + borderRadius: 8, + color: Color(0xFF193663), ), - ], - ranges: createRanges(), - annotations: [ - GaugeAnnotation( - widget: RichText( - text: TextSpan( - children: [ - TextSpan( - text: '$value', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.blue, - ), - ), - TextSpan( - text: '/$max', - style: const TextStyle(fontSize: 10, color: Colors.blue), - ), - ], + progressBar: null, // Disable the progress bar + segments: [ + GaugeSegment(from: 0, to: 1, color: Colors.red[900]!), + const GaugeSegment(from: 1, to: 2, color: Colors.red), + GaugeSegment(from: 2, to: 3, color: Colors.orange[900]!), + const GaugeSegment(from: 3, to: 4, color: Colors.orange), + const GaugeSegment(from: 4, to: 5, color: Colors.yellow), + const GaugeSegment(from: 5, to: 6, color: Colors.lightGreen), + GaugeSegment(from: 6, to: 7, color: Colors.green[600]!), + GaugeSegment(from: 7, to: 8, color: Colors.green[700]!), + GaugeSegment(from: 8, to: 9, color: Colors.green[800]!), + GaugeSegment(from: 9, to: 10, color: Colors.green[900]!), + ], + ), + ), + // Text placed inside the gauge box + Positioned( + bottom: + 30, // Position text inside the gauge without overlapping the needle + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: value.toStringAsFixed(1), + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors + .black87, + ), ), - ), - angle: 90, - positionFactor: 0.8, + const TextSpan( + text: '/10', + style: TextStyle( + fontSize: 12, + color: Colors + .black, + ), + ), + ], ), - ], + ), + ), + Positioned( + bottom: 0, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: nameIntervention, + style: const TextStyle( + fontSize: 15, + color: Colors + .black, + ), + ), + ], + ), + ), ), ], ); diff --git a/app/lib/screens/study/report/sections/results_textual_summary.dart b/app/lib/screens/study/report/sections/results_textual_summary.dart index e72a2b817..fefdd0406 100644 --- a/app/lib/screens/study/report/sections/results_textual_summary.dart +++ b/app/lib/screens/study/report/sections/results_textual_summary.dart @@ -85,7 +85,7 @@ class TextualSummaryWidget extends AverageSectionWidget { nameInterventionB, style: const TextStyle( fontSize: 16, - color: Colors.orange, + color: Colors.deepOrangeAccent, fontWeight: FontWeight.bold, ), ), diff --git a/app/pubspec.yaml b/app/pubspec.yaml index a77e299c7..0793ad070 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -25,6 +25,7 @@ dependencies: flutter_web_plugins: sdk: flutter flutter_widget_from_html: ^0.15.1 + gauge_indicator: ^0.4.3 intersperse: ^2.0.0 intl: ^0.19.0 material_design_icons_flutter: ^7.0.7296 @@ -43,7 +44,6 @@ dependencies: statistics: ^1.1.1 studyu_core: ^4.4.5 studyu_flutter_common: ^1.8.6 - syncfusion_flutter_gauges: ^20.1.59 supabase: ^2.2.4 supabase_flutter: ^2.5.8 timeline_tile: ^2.0.0