Merge pull request 'haroon_dev' (#339) from haroon_dev into master

Reviewed-on: https://34.17.182.140/Haroon6138/HMG_Patient_App_New/pulls/339
master
Haroon6138 2 days ago
commit c2cce5cba1

@ -301,7 +301,7 @@ class ApiConsts {
static String googleCloudStorageENTranslationFileBaseURL = "https://storage.googleapis.com/hmg-patientapp-translations"; static String googleCloudStorageENTranslationFileBaseURL = "https://storage.googleapis.com/hmg-patientapp-translations";
// ************ static values for Api **************** // ************ static values for Api ****************
static final double appVersionID = 21.3; static final double appVersionID = 21.4;
// static final double appVersionID = 50.7; // static final double appVersionID = 50.7;
static final int appChannelId = 3; static final int appChannelId = 3;

@ -56,7 +56,7 @@ class AppState {
void setIsPayfortHostedPageEnabled(bool value) { void setIsPayfortHostedPageEnabled(bool value) {
isPayfortHostedPageEnabled = value; isPayfortHostedPageEnabled = value;
// isPayfortHostedPageEnabled = true; // isPayfortHostedPageEnabled = false;
} }
int? _superUserID; int? _superUserID;

@ -1209,13 +1209,15 @@ class AuthenticationViewModel extends ChangeNotifier {
} }
// Fetch profile image after switching user // Fetch profile image after switching user
await _fetchProfileImage(activation.list!.first.patientId); // await _fetchProfileImage(activation.list!.first.patientId);
_fetchProfileImage(activation.list!.first.patientId);
} else { } else {
activation.list!.first.isParentUser = true; activation.list!.first.isParentUser = true;
_appState.addUserSwitchPayload(activation.list!.first.toJson(), isSuperUser: true); _appState.addUserSwitchPayload(activation.list!.first.toJson(), isSuperUser: true);
// Fetch profile image after login // Fetch profile image after login
await _fetchProfileImage(activation.list!.first.patientId); // await _fetchProfileImage(activation.list!.first.patientId);
_fetchProfileImage(activation.list!.first.patientId);
} }
activation.list!.first.bloodGroup = activation.patientBloodType; activation.list!.first.bloodGroup = activation.patientBloodType;
activation.list!.first.zipCode = selectedCountrySignup == CountryEnum.others ? '0' : selectedCountrySignup.countryCode; activation.list!.first.zipCode = selectedCountrySignup == CountryEnum.others ? '0' : selectedCountrySignup.countryCode;

@ -13,11 +13,16 @@ enum Durations {
yearly("yearly"); yearly("yearly");
final String value; final String value;
const Durations(this.value); const Durations(this.value);
} }
class HealthDataTransformation { class HealthDataTransformation {
Map<String, List<DataPoint>> transformVitalsToDataPoints(VitalsWRTType vitals, String filterType, String selectedSection,) { Map<String, List<DataPoint>> transformVitalsToDataPoints(
VitalsWRTType vitals,
String filterType,
String selectedSection,
) {
final Map<String, List<DataPoint>> dataPointMap = {}; final Map<String, List<DataPoint>> dataPointMap = {};
Map<String, List<Vitals>> data = vitals.getVitals(); Map<String, List<Vitals>> data = vitals.getVitals();
// Group data based on the filter type // Group data based on the filter type
@ -32,31 +37,36 @@ class HealthDataTransformation {
for (var vital in item) { for (var vital in item) {
String key = ""; String key = "";
if (vital.value == "" || vital.timestamp == "") continue; if (vital.value == "" || vital.timestamp == "") continue;
var parseDate = DateTime.parse(vital.timestamp);
DateTime parseDate;
try {
parseDate = DateTime.parse(vital.timestamp);
} catch (e) {
print('Error parsing timestamp "${vital.timestamp}": $e');
continue; // Skip this vital if timestamp is invalid
}
var currentDate = normalizeToStartOfDay(DateTime.now()); var currentDate = normalizeToStartOfDay(DateTime.now());
if (filterType == Durations.daily.value) { if (filterType == Durations.daily.value) {
if(isBetweenInclusive(parseDate, currentDate, DateTime.now())) { if (isBetweenInclusive(parseDate, currentDate, DateTime.now())) {
key = DateFormat('yyyy-MM-dd HH').format(DateTime.parse(vital.timestamp)); key = DateFormat('yyyy-MM-dd HH').format(parseDate);
groupedData.putIfAbsent(key, () => []).add(vital); groupedData.putIfAbsent(key, () => []).add(vital);
}// Group by hour } // Group by hour
} else if (filterType == Durations.weekly.value) { } else if (filterType == Durations.weekly.value) {
if(isBetweenInclusive(parseDate, currentDate.subtract(Duration(days: 7)), DateTime.now())) { if (isBetweenInclusive(parseDate, currentDate.subtract(Duration(days: 7)), DateTime.now())) {
key = DateFormat('yyyy-MM-dd').format(DateTime.parse(vital.timestamp)); key = DateFormat('yyyy-MM-dd').format(parseDate);
groupedData.putIfAbsent(key, () => []).add(vital); groupedData.putIfAbsent(key, () => []).add(vital);
} // Group by day } // Group by day
} else if (filterType == Durations.monthly.value) { } else if (filterType == Durations.monthly.value) {
if(isBetweenInclusive(parseDate, currentDate.subtract(Duration(days: 30)), DateTime.now())) { if (isBetweenInclusive(parseDate, currentDate.subtract(Duration(days: 30)), DateTime.now())) {
print("the value for the monthly filter is ${vital.value} with the timestamp ${vital.timestamp} and the current date is $currentDate and the parse date is $parseDate"); print("the value for the monthly filter is ${vital.value} with the timestamp ${vital.timestamp} and the current date is $currentDate and the parse date is $parseDate");
key = DateFormat('yyyy-MM-dd').format(DateTime.parse(vital.timestamp)); key = DateFormat('yyyy-MM-dd').format(parseDate);
groupedData.putIfAbsent(key, () => []).add(vital); groupedData.putIfAbsent(key, () => []).add(vital);
} // Group by day } // Group by day
} else if (filterType == Durations.halfYearly.value || filterType == Durations.yearly.value) { } else if (filterType == Durations.halfYearly.value || filterType == Durations.yearly.value) {
if(isBetweenInclusive(parseDate, currentDate.subtract(Duration(days: filterType == Durations.halfYearly.value?180: 365)), DateTime.now())) { if (isBetweenInclusive(parseDate, currentDate.subtract(Duration(days: filterType == Durations.halfYearly.value ? 180 : 365)), DateTime.now())) {
key = DateFormat('yyyy-MM').format(DateTime.parse(vital.timestamp)); key = DateFormat('yyyy-MM').format(parseDate);
groupedData.putIfAbsent(key, () => []).add(vital); groupedData.putIfAbsent(key, () => []).add(vital);
} // Group by month } // Group by month
} else { } else {
throw ArgumentError('Invalid filter type'); throw ArgumentError('Invalid filter type');
@ -68,9 +78,9 @@ class HealthDataTransformation {
groupedData.forEach((key, values) { groupedData.forEach((key, values) {
double sum = values.fold(0, (acc, v) => acc + num.parse(v.value)); double sum = values.fold(0, (acc, v) => acc + num.parse(v.value));
double mean = sum / values.length; double mean = sum / values.length;
if(selectedSection == "bodyOxygen" || selectedSection == "bodyTemperature") { if (selectedSection == "bodyOxygen" || selectedSection == "bodyTemperature") {
mean = sum / values.length; mean = sum / values.length;
}else { } else {
mean = sum; mean = sum;
} }
@ -81,7 +91,7 @@ class HealthDataTransformation {
label: key, label: key,
actualValue: finalValue.toStringAsFixed(2), actualValue: finalValue.toStringAsFixed(2),
displayTime: key, displayTime: key,
unitOfMeasurement:values.first.unitOfMeasure , unitOfMeasurement: values.first.unitOfMeasure,
time: DateTime.parse(values.first.timestamp), time: DateTime.parse(values.first.timestamp),
)); ));
}); });
@ -109,10 +119,10 @@ class HealthDataTransformation {
final random = Random(); final random = Random();
// Smooth compression scaling // Smooth compression scaling
double baseScaled = number <20 ? number:100 * (number / (number + 100)); double baseScaled = number < 20 ? number : 100 * (number / (number + 100));
// Random factor between 0.9 and 1.1 (±10%) // Random factor between 0.9 and 1.1 (±10%)
double randomFactor = number <20 ? random.nextDouble() * 1.5: 0.9 + random.nextDouble() * 0.2; double randomFactor = number < 20 ? random.nextDouble() * 1.5 : 0.9 + random.nextDouble() * 0.2;
double result = baseScaled * randomFactor; double result = baseScaled * randomFactor;
@ -122,6 +132,7 @@ class HealthDataTransformation {
DateTime normalizeToStartOfDay(DateTime date) { DateTime normalizeToStartOfDay(DateTime date) {
return DateTime(date.year, date.month, date.day); return DateTime(date.year, date.month, date.day);
} }
bool isBetweenInclusive( bool isBetweenInclusive(
DateTime target, DateTime target,
DateTime start, DateTime start,
@ -129,6 +140,4 @@ class HealthDataTransformation {
) { ) {
return !normalizeToStartOfDay(target).isBefore(start) && !normalizeToStartOfDay(target).isAfter(end); return !normalizeToStartOfDay(target).isBefore(start) && !normalizeToStartOfDay(target).isAfter(end);
} }
} }

@ -172,12 +172,12 @@ class HealthService {
} }
} }
void addWatchHelper(SmartWatchTypes watchType){ void addWatchHelper(SmartWatchTypes watchType) {
watchHelper = CreateWatchHelper.getWatchName(watchType) ; watchHelper = CreateWatchHelper.getWatchName(watchType);
} }
Future<Result<bool>> initDevice() async { Future<Result<bool>> initDevice() async {
if(watchHelper == null){ if (watchHelper == null) {
return Result.error('No watch helper found'); return Result.error('No watch helper found');
} }
return await watchHelper!.initDevice(); return await watchHelper!.initDevice();
@ -197,14 +197,14 @@ class HealthService {
await watchHelper!.getDistance(); await watchHelper!.getDistance();
await watchHelper!.getBloodOxygen(); await watchHelper!.getBloodOxygen();
Result<dynamic> data = await watchHelper!.retrieveData(); Result<dynamic> data = await watchHelper!.retrieveData();
if(data.isError) { if (data.isError) {
print('Unable to get the data'); print('Unable to get the data');
} }
var response = jsonDecode(data.asValue?.value?.toString()?.trim().replaceAll("\n", "")??""); var response = jsonDecode(data.asValue?.value?.toString()?.trim().replaceAll("\n", "") ?? "");
VitalsWRTType vitals = VitalsWRTType.fromMap(response); VitalsWRTType vitals = VitalsWRTType.fromMap(response);
log("the data is ${vitals}"); // log("the data is ${vitals}");
return vitals; return vitals;
}catch(e){ } catch (e) {
print('Error getting heart rate: $e'); print('Error getting heart rate: $e');
} }
return null; return null;

@ -9,10 +9,22 @@ class Vitals {
this.unitOfMeasure = "", this.unitOfMeasure = "",
}); });
Map<String, dynamic> toJson() {
return {
'value': value,
'timestamp': timestamp,
'uom': unitOfMeasure,
};
}
factory Vitals.fromMap(Map<dynamic, dynamic> map) { factory Vitals.fromMap(Map<dynamic, dynamic> map) {
String timestamp = map['timestamp'] ?? map['timeStamp'] ?? "";
if (timestamp.isEmpty) {
timestamp = DateTime.now().toIso8601String();
}
return Vitals( return Vitals(
value: map['value'] ?? "", value: map['value'] ?? "",
timestamp: map['timeStamp'] ?? "", timestamp: timestamp,
unitOfMeasure: map['uom'] ?? "", unitOfMeasure: map['uom'] ?? "",
); );
} }

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:async/src/result/result.dart'; import 'package:async/src/result/result.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -80,7 +81,10 @@ class HealthConnectHelper extends WatchHelper {
@override @override
Future<dynamic> retrieveData() async { Future<dynamic> retrieveData() async {
// String retData;
// retData = Result.value(getMappedData()) as String;
return Result.value(getMappedData()); return Result.value(getMappedData());
// return retData;
} }
@override @override
@ -151,9 +155,22 @@ class HealthConnectHelper extends WatchHelper {
for (var point in data) { for (var point in data) {
if (point.value is NumericHealthValue) { if (point.value is NumericHealthValue) {
final numericValue = (point.value as NumericHealthValue).numericValue; final numericValue = (point.value as NumericHealthValue).numericValue;
String timestamp = DateTime.now().toIso8601String();
try {
if (point.dateFrom != null) {
String tempTimestamp = point.dateFrom.toIso8601String();
if (tempTimestamp.isNotEmpty) {
timestamp = tempTimestamp;
}
}
} catch (e) {
debugPrint('Error converting dateFrom to ISO8601 for $s: $e');
}
Vitals vitals = Vitals( Vitals vitals = Vitals(
value: (point.value as NumericHealthValue).numericValue.toStringAsFixed(2), value: numericValue.toStringAsFixed(2),
timestamp: point.dateFrom.toString() timestamp: timestamp
); );
mappedData[s]?.add(vitals); mappedData[s]?.add(vitals);
} }
@ -165,17 +182,41 @@ class HealthConnectHelper extends WatchHelper {
for (var point in data) { for (var point in data) {
if (point.value is NumericHealthValue) { if (point.value is NumericHealthValue) {
final numericValue = (point.value as NumericHealthValue).numericValue; final numericValue = (point.value as NumericHealthValue).numericValue;
String timestamp = DateTime.now().toIso8601String();
try {
if (point.dateFrom != null) {
String tempTimestamp = point.dateFrom.toIso8601String();
if (tempTimestamp.isNotEmpty) {
timestamp = tempTimestamp;
}
}
} catch (e) {
debugPrint('Error converting dateFrom to ISO8601 for $s: $e');
}
point.value = NumericHealthValue( point.value = NumericHealthValue(
numericValue: numericValue * 100, numericValue: numericValue * 100,
); );
Vitals vitals = Vitals(value: (point.value as NumericHealthValue).numericValue.toStringAsFixed(2), timestamp: point.dateFrom.toString()); Vitals vitals = Vitals(
value: (point.value as NumericHealthValue).numericValue.toStringAsFixed(2),
timestamp: timestamp
);
mappedData[s]?.add(vitals); mappedData[s]?.add(vitals);
} }
} }
} }
getMappedData() { getMappedData() {
return " { \"heartRate\": ${mappedData["heartRate"] ?? []}, \"sleep\": ${mappedData["sleep"] ?? []}, \"steps\": ${mappedData["steps"] ?? []}, \"activity\": ${mappedData["activity"] ?? []}, \"bloodOxygen\": ${mappedData["bloodOxygen"] ?? []}, \"bodyTemperature\": ${mappedData["bodyTemperature"] ?? []}, \"distance\": ${mappedData["distance"] ?? []} }"; return jsonEncode({
"heartRate": (mappedData["heartRate"] ?? []).map((v) => v.toJson()).toList(),
"sleep": (mappedData["sleep"] ?? []).map((v) => v.toJson()).toList(),
"steps": (mappedData["steps"] ?? []).map((v) => v.toJson()).toList(),
"activity": (mappedData["activity"] ?? []).map((v) => v.toJson()).toList(),
"bloodOxygen": (mappedData["bloodOxygen"] ?? []).map((v) => v.toJson()).toList(),
"bodyTemperature": (mappedData["bodyTemperature"] ?? []).map((v) => v.toJson()).toList(),
"distance": (mappedData["distance"] ?? []).map((v) => v.toJson()).toList(),
});
} }
getHeartData(DateTime startDate, DateTime endDate, HealthDataType types) async { getHeartData(DateTime startDate, DateTime endDate, HealthDataType types) async {

@ -212,6 +212,7 @@ class _SearchDoctorByNameState extends State<SearchDoctorByName> {
doctorsListResponseModel: bookAppointmentsVM.filteredDoctorList[index], doctorsListResponseModel: bookAppointmentsVM.filteredDoctorList[index],
isLoading: false, isLoading: false,
bookAppointmentsViewModel: bookAppointmentsViewModel, bookAppointmentsViewModel: bookAppointmentsViewModel,
isDoctorNameSearch: true,
).paddingSymmetrical(16.h, 0.h).onPress(() async { ).paddingSymmetrical(16.h, 0.h).onPress(() async {
bookAppointmentsVM.setSelectedDoctor(bookAppointmentsVM.filteredDoctorList[index]); bookAppointmentsVM.setSelectedDoctor(bookAppointmentsVM.filteredDoctorList[index]);
LoaderBottomSheet.showLoader(); LoaderBottomSheet.showLoader();

@ -10,13 +10,17 @@ 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/extensions/widget_extensions.dart';
import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/book_appointments_view_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart'; import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/doctors_list_response_model.dart';
import 'package:hmg_patient_app_new/features/book_appointments/models/resp_models/get_clinic_list_response_model.dart';
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart'; import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/dental_chief_complaints_page.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/laser/laser_appointment.dart';
import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart'; import 'package:hmg_patient_app_new/presentation/book_appointment/widgets/appointment_calendar.dart';
import 'package:hmg_patient_app_new/theme/colors.dart'; import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart'; import 'package:hmg_patient_app_new/widgets/buttons/custom_button.dart';
import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart'; import 'package:hmg_patient_app_new/widgets/chip/app_custom_chip_widget.dart';
import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart'; import 'package:hmg_patient_app_new/widgets/common_bottom_sheet.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart'; import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:lottie/lottie.dart'; import 'package:lottie/lottie.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@ -25,11 +29,13 @@ class DoctorCard extends StatelessWidget {
super.key, super.key,
required this.doctorsListResponseModel, required this.doctorsListResponseModel,
required this.isLoading, required this.isLoading,
this.isDoctorNameSearch = false,
required this.bookAppointmentsViewModel, required this.bookAppointmentsViewModel,
}); });
final DoctorsListResponseModel doctorsListResponseModel; final DoctorsListResponseModel doctorsListResponseModel;
final bool isLoading; final bool isLoading;
final bool isDoctorNameSearch;
final BookAppointmentsViewModel bookAppointmentsViewModel; final BookAppointmentsViewModel bookAppointmentsViewModel;
@ -173,6 +179,29 @@ class DoctorCard extends StatelessWidget {
CustomButton( CustomButton(
text: LocaleKeys.bookAppo.tr(context: context), text: LocaleKeys.bookAppo.tr(context: context),
onPressed: () async { onPressed: () async {
if (isDoctorNameSearch && doctorsListResponseModel.clinicID == 17) {
GetClinicsListResponseModel selectedClinic = GetClinicsListResponseModel(
clinicID: doctorsListResponseModel.clinicID, clinicDescription: doctorsListResponseModel.clinicName, isLiveCareClinicAndOnline: false, liveCareServiceID: 0, liveCareClinicID: 0);
bookAppointmentsViewModel.setProjectID(doctorsListResponseModel.projectID.toString());
bookAppointmentsViewModel.setSelectedClinic(selectedClinic);
bookAppointmentsViewModel.setIsChiefComplaintsListLoading(true);
Navigator.of(context).push(
CustomPageRoute(
page: DentalChiefComplaintsPage(),
),
);
} else if (isDoctorNameSearch && doctorsListResponseModel.clinicID == 253) {
GetClinicsListResponseModel selectedClinic = GetClinicsListResponseModel(
clinicID: doctorsListResponseModel.clinicID, clinicDescription: doctorsListResponseModel.clinicName, isLiveCareClinicAndOnline: false, liveCareServiceID: 0, liveCareClinicID: 0);
bookAppointmentsViewModel.setSelectedClinic(selectedClinic);
bookAppointmentsViewModel.getLaserClinic();
bookAppointmentsViewModel.setIsDoctorsListLoading(true);
Navigator.of(context).push(
CustomPageRoute(
page: LaserAppointment(),
),
);
} else {
bookAppointmentsViewModel.setSelectedDoctor(doctorsListResponseModel); bookAppointmentsViewModel.setSelectedDoctor(doctorsListResponseModel);
LoaderBottomSheet.showLoader(); LoaderBottomSheet.showLoader();
bookAppointmentsViewModel.isLiveCareSchedule bookAppointmentsViewModel.isLiveCareSchedule
@ -261,6 +290,7 @@ class DoctorCard extends StatelessWidget {
// isCloseButtonVisible: true, // isCloseButtonVisible: true,
// ); // );
}); });
}
}, },
backgroundColor: Color(0xffFEE9EA), backgroundColor: Color(0xffFEE9EA),
borderColor: Color(0xffFEE9EA), borderColor: Color(0xffFEE9EA),

@ -240,7 +240,8 @@ class _ActivityDetailsState extends State<ActivityDetails> {
return Selector<HealthProvider, Map<String, List<DataPoint>>?>( return Selector<HealthProvider, Map<String, List<DataPoint>>?>(
selector: (_, model) => model.selectedData, selector: (_, model) => model.selectedData,
builder: (_, data, __) { builder: (_, data, __) {
if (context.read<HealthProvider>().selectedData.values.toList().first?.isEmpty == true) return SizedBox(); // if (context.read<HealthProvider>().selectedData.values.toList().first.isEmpty == true) return SizedBox();
if (context.read<HealthProvider>().selectedData.values.toList().isEmpty == true) return SizedBox();
return CustomBarChart( return CustomBarChart(
dataPoints: context.read<HealthProvider>().selectedData.values.toList().first, dataPoints: context.read<HealthProvider>().selectedData.values.toList().first,

@ -2,8 +2,8 @@ name: hmg_patient_app_new
description: "New HMG Patient App" description: "New HMG Patient App"
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 0.0.37+36 #version: 0.0.38+37
#version: 0.0.6+3 version: 0.0.7+1
environment: environment:
sdk: ">=3.6.0 <4.0.0" sdk: ">=3.6.0 <4.0.0"

Loading…
Cancel
Save