uaestats_fe/lib/presentation/components/indicators/indicator_view.dart
2026-05-16 11:31:32 +05:30

286 lines
9.6 KiB
Dart
Executable File

import 'package:external_repos/external_repos.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:uae_stat/config/my_theme.dart';
import 'package:uae_stat/domain/use_cases/language.dart';
import 'package:uae_stat/domain/use_cases/stat_data/indicator_use_case.dart';
import 'package:uae_stat/infrastructure/services/packages/num_abbreviation.dart';
import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart';
import 'package:uae_stat/presentation/components/space.dart';
/// constrain into a fixed height
class IndicatorView extends ConsumerWidget {
const IndicatorView(
this.id, {
super.key,
});
final IndicatorEnum id;
void onPressed(
BuildContext context,
WidgetRef ref,
) {
final location =
'/${context.language}/${BottomNavBarItem.uaeNumbers.routePath}/${id.name}';
context.go(location);
}
@override
Widget build(BuildContext context, WidgetRef ref) {
final topicColor = MyTheme.topicColor(
id.topic,
);
final title = Text(
context.translate(
id.titleEN,
id.titleAR,
),
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
color: Colors.black,
),
);
final provider = IndicatorProvider(id);
return ref
.watch(
provider,
)
.when(
skipLoadingOnRefresh: false,
skipLoadingOnReload: false,
skipError: false,
data: (indicatorData) {
final value = switch (id) {
// econ
IndicatorEnum.gdpGrowthConstant =>
(indicatorData as GdpEntity).constant.gdpGrowthRate.value,
// env
IndicatorEnum.exportOilQuantity =>
(indicatorData as OilEntity).crudeOilExports.value,
IndicatorEnum.municipalWaste =>
(indicatorData as WaterEntity).municipalWaste.value,
// social
IndicatorEnum.hospitalsPrivate =>
(indicatorData as HospitalsEntity).numPrivate.value,
_ => indicatorData.level1Data.value,
};
final subtitleText = switch (id) {
// econ
IndicatorEnum.gdpGrowthConstant =>
(indicatorData as GdpEntity).constant.gdpGrowthRate.subtitle,
// env
IndicatorEnum.exportOilQuantity =>
(indicatorData as OilEntity).crudeOilExports.subtitle,
IndicatorEnum.municipalWaste =>
(indicatorData as WaterEntity).municipalWaste.subtitle,
// social
IndicatorEnum.hospitalsPrivate =>
(indicatorData as HospitalsEntity).numPrivate.subtitle,
_ => indicatorData.level1Data.subtitle,
};
final hasPercentage = switch (id) {
// econ
IndicatorEnum.gdpGrowthConstant => (indicatorData as GdpEntity)
.constant
.gdpGrowthRate
.isValuePercentage,
// env
IndicatorEnum.exportOilQuantity =>
(indicatorData as OilEntity).crudeOilExports.isValuePercentage,
IndicatorEnum.municipalWaste =>
(indicatorData as WaterEntity).municipalWaste.isValuePercentage,
// social
IndicatorEnum.hospitalsPrivate =>
(indicatorData as HospitalsEntity).numPrivate.isValuePercentage,
_ => indicatorData.level1Data.isPercentage,
};
// title + subtitle on separate lines
final subtitle = Text(
context.translateFromTuple(
subtitleText,
),
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
color: Colors.black45,
),
);
final textDescriptorBody = ConstrainedBox(
constraints: BoxConstraints(
maxWidth: context.translate(130, 170).toDouble(),
),
child: Column(
children: [
title,
subtitle,
],
),
);
final textValue = Text(
'${value > 9999999 ? value.toAbbreviatedString() : value.toStringWithCommas(
hideDecimals: value > 99999,
)}${(hasPercentage ? '%' : '')}',
style: TextStyle(
fontFamily:
// ref.watch(languageProvider) == Language.ar
// ? 'NotoKufi'
// :
'Roboto',
color: topicColor,
fontSize: 24,
fontWeight: FontWeight.w800,
// height: context.translate(null, 1.75),
),
);
return InkWell(
onTap: id == IndicatorEnum.municipalWaste
? null
: () => onPressed(context, ref),
borderRadius: BorderRadius.circular(10),
child: Container(
padding: const EdgeInsets.only(
top: 4,
bottom: 0,
left: 12,
right: 12,
),
decoration: BoxDecoration(
border: Border.all(
color: topicColor,
),
borderRadius: BorderRadius.circular(10),
),
child: FittedBox(
fit: BoxFit.scaleDown,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
textDescriptorBody,
if (context.language == LanguageLocale.enUS)
6.verticalSpace,
textValue,
],
),
),
),
);
},
error: (err, stackTrace) {
Future(() => Error.throwWithStackTrace(err, stackTrace));
Future.delayed(
const Duration(seconds: 5),
() {
if (!context.mounted) return;
ref.invalidate(provider);
},
);
final textDescriptorBody = ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 130,
),
child: title,
);
final value = Text(
'!',
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
color: Colors.red,
fontSize: 24,
fontWeight: FontWeight.w900,
),
);
return InkWell(
onTap: id == IndicatorEnum.municipalWaste
? null
: () => onPressed(context, ref),
borderRadius: BorderRadius.circular(10),
child: Container(
padding: const EdgeInsets.only(
top: 4,
bottom: 0,
left: 12,
right: 12,
),
decoration: BoxDecoration(
border: Border.all(
color: topicColor,
),
borderRadius: BorderRadius.circular(10),
),
child: FittedBox(
fit: BoxFit.scaleDown,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
textDescriptorBody,
6.verticalSpace,
value,
],
),
),
),
);
},
loading: () {
final textDescriptorBody = ConstrainedBox(
constraints: const BoxConstraints(
maxWidth: 130,
),
child: title,
);
final value = SizedBox(
height: 24,
width: 24,
child: LinearProgressIndicator(
borderRadius: BorderRadius.circular(100),
color: MyTheme.topicColor(id.topic),
),
);
return InkWell(
onTap: id == IndicatorEnum.municipalWaste
? null
: () => onPressed(context, ref),
borderRadius: BorderRadius.circular(10),
child: Container(
padding: const EdgeInsets.only(
top: 4,
bottom: 0,
left: 12,
right: 12,
),
decoration: BoxDecoration(
border: Border.all(
color: topicColor,
),
borderRadius: BorderRadius.circular(10),
),
child: FittedBox(
fit: BoxFit.scaleDown,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
textDescriptorBody,
6.verticalSpace,
value,
],
),
),
),
);
},
);
}
}