You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
HMG_Patient_App_New/lib/presentation/smartwatches/activity_detail.dart

360 lines
13 KiB
Dart

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<ActivityDetails> createState() => _ActivityDetailsState();
}
class _ActivityDetailsState extends State<ActivityDetails> {
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<HealthProvider>().setDurations(durations.Durations.daily);
break;
case 1:
context.read<HealthProvider>().setDurations(durations.Durations.weekly);
break;
case 2:
context.read<HealthProvider>().setDurations(durations.Durations.monthly);
break;
case 3:
context.read<HealthProvider>().setDurations(durations.Durations.halfYearly);
break;
case 4:
context.read<HealthProvider>().setDurations(durations.Durations.yearly);
break;
}
context.read<HealthProvider>().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<HealthProvider, Tuple2<double?, String?>>(
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,
1 month ago
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); // 100150
// final List<DataPoint> 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<DataPoint> 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<DataPoint> 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<HealthProvider, Map<String, List<DataPoint>>?>(
selector: (_, model) => model.selectedData,
builder: (_, data, __) {
if (context.read<HealthProvider>().selectedData.values.toList().first?.isEmpty == true) return SizedBox();
return CustomBarChart(
dataPoints: context.read<HealthProvider>().selectedData.values.toList().first,
height: 300.h,
maxY: 150,
barColor: AppColors.bgGreenColor,
1 month ago
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<HealthProvider>().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<HealthProvider>().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);
}
1 month ago
double getBarWidth() {
var duration = context.read<HealthProvider>().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;
}
}
}