import 'dart:math'; import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/core/common_models/data_points.dart'; import 'package:hmg_patient_app_new/extensions/string_extensions.dart'; import 'package:hmg_patient_app_new/extensions/widget_extensions.dart'; import 'package:hmg_patient_app_new/features/smartwatch_health_data/health_provider.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart'; import 'package:hmg_patient_app_new/widgets/custom_tab_bar.dart'; import 'package:hmg_patient_app_new/widgets/graph/CustomBarGraph.dart'; import 'package:intl/intl.dart' show DateFormat; import 'package:provider/provider.dart'; import 'package:hmg_patient_app_new/features/smartwatch_health_data/HealthDataTransformation.dart' as durations; import 'package:dartz/dartz.dart' show Tuple2; import '../../core/utils/date_util.dart'; class ActivityDetails extends StatefulWidget { final String selectedActivity; final String sectionName; final String uom; const ActivityDetails({super.key, required this.selectedActivity, required this.sectionName, required this.uom}); @override State createState() => _ActivityDetailsState(); } class _ActivityDetailsState extends State { int index = 0; @override void initState() { super.initState(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColors.bgScaffoldColor, body: CollapsingListView( title: "All Health Data".needTranslation, child: Column( spacing: 16.h, children: [ periodSelectorView((index) {}), activityDetails(), DecoratedBox( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h), child: activityGraph().paddingOnly(left: 16.w, right: 16.w, top: 32.h, bottom: 16.h),) ], ).paddingSymmetrical(24.w, 24.h), ), ); } Widget periodSelectorView(Function(int) onItemSelected) { return DecoratedBox( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h), child: Row( children: [ Expanded( child: CustomTabBar( activeTextColor: Color(0xffED1C2B), activeBackgroundColor: Color(0xffED1C2B).withValues(alpha: .1), tabs: [ CustomTabBarModel(null, "D"), CustomTabBarModel(null, "W"), CustomTabBarModel(null, "M"), CustomTabBarModel(null, "6M"), CustomTabBarModel(null, "Y"), // CustomTabBarModel(null, "Completed".needTranslation), ], shouldTabExpanded: true, onTabChange: (index) { switch (index) { case 0: context.read().setDurations(durations.Durations.daily); break; case 1: context.read().setDurations(durations.Durations.weekly); break; case 2: context.read().setDurations(durations.Durations.monthly); break; case 3: context.read().setDurations(durations.Durations.halfYearly); break; case 4: context.read().setDurations(durations.Durations.yearly); break; } context.read().fetchData(); }, ), ), ], ).paddingSymmetrical(4.w, 4.h)); } Widget activityDetails() { return DecoratedBox( decoration: RoundedRectangleBorder().toSmoothCornerDecoration(color: AppColors.whiteColor, borderRadius: 12.h, hasShadow: true), child: Column( spacing: 8.h, crossAxisAlignment: CrossAxisAlignment.start, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ widget.sectionName.capitalizeFirstofEach.toText32(weight: FontWeight.w600, color: AppColors.textColor), "Average".toText12(fontWeight: FontWeight.w500, color: AppColors.greyTextColor) ], ), Selector>( selector: (_, model) => Tuple2(model.averageValue, model.averageValueString), builder: (_, data, __) { var averageAsDouble = data.value1; var averageAsString = data.value2; return Row( crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, spacing: 4.w, children: [ (averageAsDouble?.toStringAsFixed(2) ?? averageAsString ?? "N/A").toText24(color: AppColors.textGreenColor, fontWeight: FontWeight.w600), Visibility( visible: averageAsDouble != null || averageAsString != null, child: widget.uom.toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w500) ) ], ); }) ], ).paddingSymmetrical(16.w, 16.h)); } Widget activityGraph() { // final _random = Random(); // // int randomBP() => 100 + _random.nextInt(51); // 100–150 // final List data6Months = List.generate(6, (index) { // final date = DateTime.now().subtract(Duration(days: 30 * (5 - index))); // // final value = randomBP(); // // return DataPoint( // value: value.toDouble(), // label: value.toString(), // actualValue: value.toString(), // displayTime: DateFormat('MMM').format(date), // unitOfMeasurement: 'mmHg', // time: date, // ); // }); // final List data12Months = List.generate(12, (index) { // final date = DateTime.now().subtract(Duration(days: 30 * (11 - index))); // // final value = randomBP(); // // return DataPoint( // value: value.toDouble(), // label: value.toString(), // actualValue: value.toString(), // displayTime: DateFormat('MMM').format(date), // unitOfMeasurement: 'mmHg', // time: date, // ); // }); // // List data =[]; // if(index == 0){ // data = data6Months; // } else if(index == 1){ // data = data12Months; // } else // data = [ // DataPoint( // value: 128, // label: "128", // actualValue: '128', // displayTime: 'Sun', // unitOfMeasurement: 'mmHg', // time: DateTime.now().subtract(const Duration(days: 6)), // ), // DataPoint( // value: 135, // label: "135", // actualValue: '135', // displayTime: 'Mon', // unitOfMeasurement: 'mmHg', // time: DateTime.now().subtract(const Duration(days: 5)), // ), // DataPoint( // value: 122, // label: "122", // actualValue: '122', // displayTime: 'Tue', // unitOfMeasurement: 'mmHg', // time: DateTime.now().subtract(const Duration(days: 4)), // ), // DataPoint( // value: 140, // label: "140", // actualValue: '140', // displayTime: 'Wed', // unitOfMeasurement: 'mmHg', // time: DateTime.now().subtract(const Duration(days: 3)), // ), // DataPoint( // value: 118, // label: "118", // actualValue: '118', // displayTime: 'Thu', // unitOfMeasurement: 'mmHg', // time: DateTime.now().subtract(const Duration(days: 2)), // ), // DataPoint( // value: 125, // label: "125", // actualValue: '125', // displayTime: 'Fri', // unitOfMeasurement: 'mmHg', // time: DateTime.now().subtract(const Duration(days: 1)), // ), // DataPoint( // value: 130, // label: "130", // actualValue: '130', // displayTime: 'Sat', // unitOfMeasurement: 'mmHg', // time: DateTime.now(), // ),23 // ]; return Selector>?>( selector: (_, model) => model.selectedData, builder: (_, data, __) { if (context.read().selectedData.values.toList().first?.isEmpty == true) return SizedBox(); return CustomBarChart( dataPoints: context.read().selectedData.values.toList().first, height: 300.h, maxY: 150, barColor: AppColors.bgGreenColor, barWidth: getBarWidth(), barRadius: BorderRadius.circular(8), bottomLabelColor: Colors.black, bottomLabelSize: 12, leftLabelInterval: .1, leftLabelReservedSize: 20, // Left axis label formatter (Y-axis) leftLabelFormatter: (value) { var labelValue = double.tryParse(value.toStringAsFixed(0)); if (labelValue == null) return SizedBox.shrink(); // if (labelValue == 0 || labelValue == 150 / 2 || labelValue == 150) { // return Text( // labelValue.toStringAsFixed(0), // style: const TextStyle( // color: Colors.black26, // fontSize: 11, // ), // ); // } return SizedBox.shrink(); }, /// for the handling of the sleep time getTooltipItem: (widget.selectedActivity == "sleep") ? (data) { return BarTooltipItem( '${DateUtil. millisToHourMin(num.parse(data.actualValue).toInt())}\n${DateFormat('dd MMM, yyyy').format(data.time)}', TextStyle( color: Colors.black, fontSize: 12.f, fontWeight: FontWeight.w500, ), ); } : null, // Bottom axis label formatter (X-axis - Days) bottomLabelFormatter: (value, dataPoints) { final index = value.toInt(); print("value is $value"); print("the index is $index"); print("the dataPoints.length is ${dataPoints.length}"); var bottomText = ""; var date = dataPoints[index].time; print("the time is ${date}"); switch (context.read().selectedDuration) { case durations.Durations.daily: bottomText = getHour(date).toString(); break; case durations.Durations.weekly: bottomText = getDayName(date)[0]; break; case durations.Durations.monthly: case durations.Durations.halfYearly: case durations.Durations.yearly: bottomText = getMonthName(date)[0]; } return Text( bottomText, style: const TextStyle( color: Colors.grey, fontSize: 11, ), ); return const Text(''); }, verticalInterval: 1 / context.read().selectedData.values.toList().first.length, getDrawingVerticalLine: (value) { return FlLine( color: AppColors.greyColor, strokeWidth: 1, ); }, showGridLines: true); }); } //todo remove these from here String getDayName(DateTime date) { return DateUtil.getWeekDayAsOfLang(date.weekday); } String getHour(DateTime date) { return date.hour.toString().padLeft(2, '0').toString(); } static String getMonthName(DateTime date) { return DateUtil.getMonthDayAsOfLang(date.month); } double getBarWidth() { var duration = context.read().selectedDuration; switch(duration){ case durations.Durations.daily: return 26.w; case durations.Durations.weekly: return 26.w; case durations.Durations.monthly: return 6.w; case durations.Durations.halfYearly: return 26.w; case durations.Durations.yearly: return 18.w; } } }