import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/packages/list.dart'; import 'package:uae_stat/infrastructure/services/packages/num_abbreviation.dart'; import 'package:uae_stat/presentation/components/space.dart'; class ThemedDistributionChart extends ConsumerWidget { const ThemedDistributionChart( this.data, { required this.leftColor, required this.middleText, required this.rightColor, this.doSort = true, this.labelBuilder, super.key, }); final bool doSort; final String middleText; final Map data; final Color leftColor; final Color rightColor; final String Function(bool isStart, num value)? labelBuilder; Map calculateSortedData() { final sortedEntries = data.entries.toList() ..sort( (a, b) { final aSum = a.value.left + a.value.right; final bSum = b.value.left + b.value.right; return bSum.compareTo(aSum); }, ); return Map.fromEntries(sortedEntries); } @override Widget build(BuildContext context, WidgetRef ref) { final sortedDataIfAskedElseUnsorted = doSort ? calculateSortedData() : data; final maxVal = data.values.fold( double.negativeInfinity, (prev, vals) { final localMax = max(vals.left, vals.right); return localMax > prev ? localMax : prev; }, ); const textSpace = 37.0; final left = Column( children: sortedDataIfAskedElseUnsorted.values.map( (e) { final bar = FractionallySizedBox( widthFactor: e.left / maxVal, child: DecoratedBox( decoration: BoxDecoration( color: leftColor, borderRadius: const BorderRadiusDirectional.horizontal( start: Radius.circular(100), ), ), child: double.infinity.verticalSpace, ), ); final text = Text( labelBuilder == null ? e.left.toStringWithCommas() : labelBuilder!(true, e.left), textAlign: TextAlign.end, style: TextStyle( fontFamily: context.translate( 'Roboto', 'NotoKufi', ), fontSize: 11, fontWeight: FontWeight.w500, ), ); final segment = Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.end, children: [ SizedBox( width: textSpace, child: text, ), 4.horizontalSpace, Flexible( child: bar, ), ], ), ); return segment; }, ).toList() ..intersperseDivider( 8.verticalSpace, ) ..insert( 0, Padding( padding: const EdgeInsets.only(bottom: 4), child: Text( 'Male', style: TextStyle( fontFamily: context.translate( 'Roboto', 'NotoKufi', ), fontSize: 11, fontWeight: FontWeight.w800, ), ), ), ), ); final right = Column( children: sortedDataIfAskedElseUnsorted.values.map( (e) { final bar = FractionallySizedBox( widthFactor: e.right / maxVal, child: DecoratedBox( decoration: BoxDecoration( color: rightColor, borderRadius: const BorderRadiusDirectional.horizontal( end: Radius.circular(100), ), ), child: double.infinity.verticalSpace, ), ); final text = Text( labelBuilder == null ? e.right.toStringWithCommas() : labelBuilder!(true, e.right), textAlign: TextAlign.start, style: TextStyle( fontFamily: context.translate( 'Roboto', 'NotoKufi', ), fontSize: 11, fontWeight: FontWeight.w500, ), ); final segment = Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Flexible( child: bar, ), 4.horizontalSpace, SizedBox( width: textSpace, child: text, ), ], ), ); return segment; }, ).toList() ..intersperseDivider( 8.verticalSpace, ) ..insert( 0, Padding( padding: const EdgeInsets.only(bottom: 4), child: Text( 'Female', style: TextStyle( fontFamily: context.translate( 'Roboto', 'NotoKufi', ), fontSize: 11, fontWeight: FontWeight.w800, ), ), ), ), ); final legend = Column( children: sortedDataIfAskedElseUnsorted.keys .map( (e) => Expanded( child: Center( child: Text( e, textAlign: TextAlign.center, style: TextStyle( fontFamily: context.translate( 'Roboto', 'NotoKufi', ), fontSize: 11, fontWeight: FontWeight.w900, ), ), ), ), ) .toList() ..intersperseDivider( 8.verticalSpace, ) ..insert( 0, Padding( padding: const EdgeInsets.only(bottom: 4), child: Text( middleText, textAlign: TextAlign.center, maxLines: 1, style: TextStyle( fontFamily: context.translate( 'Roboto', 'NotoKufi', ), fontSize: 11, fontWeight: FontWeight.w800, ), ), ), ), ); return Row( children: [ Expanded( child: left, ), ConstrainedBox( constraints: const BoxConstraints(maxWidth: 60), child: Padding( padding: const EdgeInsets.symmetric( horizontal: 6, ), child: legend, ), ), Expanded( child: right, ), ], ); } }