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/features/lab/lab_view_model.dart

464 lines
14 KiB
Dart

import 'dart:core';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:hmg_patient_app_new/core/app_assets.dart';
import 'package:hmg_patient_app_new/core/common_models/data_points.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart' show Utils;
import 'package:hmg_patient_app_new/features/lab/lab_repo.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/lab_result.dart';
import 'package:hmg_patient_app_new/features/lab/models/resp_models/patient_lab_orders_response_model.dart';
import 'package:hmg_patient_app_new/presentation/lab/lab_results/lab_result_details.dart';
import 'package:hmg_patient_app_new/services/error_handler_service.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/theme/colors.dart';
import 'package:hmg_patient_app_new/widgets/loader/bottomsheet_loader.dart';
import 'package:intl/intl.dart' show DateFormat;
import 'package:logger/logger.dart';
class LabViewModel extends ChangeNotifier {
bool isLabOrdersLoading = false;
bool isLabResultsLoading = false;
LabRepo labRepo;
ErrorHandlerService errorHandlerService;
NavigationService navigationService;
List<PatientLabOrdersResponseModel> patientLabOrders = [];
List<PatientLabOrdersResponseModel> filteredLabOrders = [];
List<PatientLabOrdersResponseModel> tempLabOrdersList = [];
List<LabResult> mainLabResults = [];
List<DataPoint> mainGraphPoints = [];
List<DataPoint> filteredGraphValues = [];
List months = [
'Jan',
'Feb',
'Mar',
'April',
'May',
'Jun',
'July',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
];
2 months ago
late List<String> _labSuggestionsList = [];
2 months ago
List<String> get labSuggestions => _labSuggestionsList;
Set<TestDetails> uniqueTests = {};
double maxY = 0.0;
double maxX = double.infinity;
LabViewModel(
{required this.labRepo,
required this.errorHandlerService,
required this.navigationService});
initLabProvider() {
patientLabOrders.clear();
filteredLabOrders.clear();
isLabOrdersLoading = true;
isLabResultsLoading = true;
getPatientLabOrders();
notifyListeners();
}
Future<void> getPatientLabOrders({Function(dynamic)? onSuccess, Function(String)? onError}) async {
2 months ago
final result = await labRepo.getPatientLabOrders();
result.fold(
(failure) async {
isLabOrdersLoading = false;
isLabResultsLoading = false;
notifyListeners();
},
// => await errorHandlerService.handleError(failure: failure),
(apiResponse) {
if (apiResponse.messageStatus == 2) {
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if (apiResponse.messageStatus == 1) {
patientLabOrders = apiResponse.data!;
filteredLabOrders = List.from(patientLabOrders);
tempLabOrdersList = apiResponse.data!;
isLabOrdersLoading = false;
isLabResultsLoading = false;
2 months ago
filterSuggestions();
getUniqueTestDescription();
notifyListeners();
if (onSuccess != null) {
onSuccess(apiResponse);
}
}
},
);
}
filterSuggestions() {
2 months ago
final List<String> labels = patientLabOrders
.expand((order) => order.testDetails!)
.map((detail) => detail.description)
.whereType<String>()
2 months ago
.toList();
_labSuggestionsList = labels.toSet().toList();
notifyListeners();
}
filterLabReports(String query) {
if (query.isEmpty) {
filteredLabOrders = List.from(patientLabOrders); // reset
} else {
filteredLabOrders = patientLabOrders.where((order) {
final descriptions = order.testDetails?.map((d) => d.description?.toLowerCase()).toList() ?? [];
return descriptions.any((desc) => desc != null && desc.contains(query.toLowerCase()));
}).toList();
patientLabOrders = filteredLabOrders;
}
2 months ago
notifyListeners();
}
getUniqueTestDescription() {
uniqueTests = {
for (var item in patientLabOrders)
if (item.testDetails != null)
...?item.testDetails?.map<TestDetails>((test) => TestDetails(
description: test.description.toString(),
testCode: test.testCode.toString(),
testID: test.testID,
createdOn: item.createdOn,
model: item))
};
}
Future<void> getPatientLabResult(
PatientLabOrdersResponseModel laborder, String procedureName) async {
LoaderBottomSheet.showLoader();
mainLabResults.clear();
filteredGraphValues.clear();
maxY = double.negativeInfinity;
final result = await labRepo.getPatientLabResults(
laborder,
Utils.isVidaPlusProject(int.parse(laborder.projectID ?? "0")),
procedureName);
result.fold(
(failure) async {
LoaderBottomSheet.hideLoader();
await errorHandlerService.handleError(failure: failure);
},
(apiResponse) {
LoaderBottomSheet.hideLoader();
if (apiResponse.messageStatus == 2) {
} else if (apiResponse.messageStatus == 1) {
var sortedResponse = sortByFlagAndValue(apiResponse.data!);
var recentThree = sort(sortedResponse);
mainLabResults = recentThree;
double counter = 1;
recentThree.reversed.forEach((element) {
try {
var dateTime =
DateUtil.convertStringToDate(element.verifiedOnDateTime!);
var resultValue = double.parse(element.resultValue!);
var transformedValue = transformValueInRange(double.parse(element.resultValue!), element.calculatedResultFlag??"");
if (resultValue>maxY) {
maxY = resultValue;
maxX = maxY;
}
filteredGraphValues.add(DataPoint(
value: transformedValue,
actualValue:element.resultValue!,
label: formatDateAsMMYY(dateTime),
displayTime: resultDate(dateTime),
time: DateUtil.convertStringToDate(element.verifiedOnDateTime),
referenceValue: element.calculatedResultFlag ?? "",
));
counter++;
} catch (e) {}
});
LabResult recentResult = recentThree.first;
recentResult.verifiedOn = resultDate(DateUtil.convertStringToDate(recentResult.verifiedOnDateTime!));
// filteredGraphValues = [filteredGraphValues.first];
navigationService.push(MaterialPageRoute(
builder: (_) =>
LabResultDetails(recentLabResult: recentResult)));
notifyListeners();
}
},
);
}
String resultDate(DateTime date){
return '${date.day} ${months[date.month-1]},${date.year}';
}
double transformValueInRange(double inputValue, String flag) {
// Define range boundaries
double rangeStart, rangeEnd;
switch (flag) {
case'LCL':
case 'CL':
rangeStart = 0.0;
rangeEnd = 19.0;
break;
case 'L':
rangeStart = 20.0;
rangeEnd = 39.0;
break;
case 'N':
rangeStart = 40.0;
rangeEnd = 59.0;
break;
case 'H':
rangeStart = 60.0;
rangeEnd = 79.0;
break;
case 'HCH':
case 'CH':
rangeStart = 80.0;
rangeEnd = 100.0;
break;
default:
throw ArgumentError('Invalid flag: $flag');
}
// Clamp input value to 0-100 and map it to the range bounds
final clampedValue = inputValue.clamp(0.0, 100.0);
final normalizedValue = clampedValue / 100.0; // Normalize input to 0-1
// Map the normalized value to the target range bounds
final transformedValue = rangeStart + ((normalizedValue * (rangeEnd - rangeStart)));
debugPrint("the actual value is $inputValue");
debugPrint("the flag is $flag");
debugPrint("the transformed value is $transformedValue");
return transformedValue;
}
void getSelectedDateRange(DateTime? start, DateTime? end) {
maxY = double.negativeInfinity;
if(start == null && end == null) {
mainLabResults.forEach((element) {
final time = DateUtil.convertStringToDate(element.verifiedOnDateTime!);
try{
var resultValue = double.parse(element.resultValue!);
var transformedValue = transformValueInRange(double.parse(element.resultValue!), element.calculatedResultFlag??"");
if (resultValue > maxY) {
maxY = resultValue;
}
filteredGraphValues.add(DataPoint(
value: transformedValue,
actualValue: element.resultValue!,
label: formatDateAsMMYY(time),
displayTime: resultDate(time),
time: DateUtil.convertStringToDate(element.verifiedOnDateTime),
referenceValue: element.calculatedResultFlag ?? "",
));
}catch(e){
}
});
}else {
filteredGraphValues.clear();
mainLabResults.forEach((element) {
try {
var dateTime =
DateUtil.convertStringToDate(element.verifiedOnDateTime!);
var resultValue = double.parse(element.resultValue!);
var transformedValue = transformValueInRange(double.parse(element.resultValue!), element.calculatedResultFlag??"");
if (resultValue > maxY) {
maxY = resultValue;
}
if (start != null && end == null) {
if (dateTime.isAtSameMomentAs(start)) {
filteredGraphValues.add(DataPoint(
value: transformedValue,
actualValue: element.resultValue!,
label: formatDateAsMMYY(dateTime),
displayTime: resultDate(dateTime),
time:
DateUtil.convertStringToDate(element.verifiedOnDateTime),
referenceValue: element.calculatedResultFlag ?? ""));
}
} else if (start != null && end != null) {
if ((dateTime.isAfter(start)) && (dateTime.isBefore(end))) {
filteredGraphValues.add(DataPoint(
value: transformedValue,
actualValue: element.resultValue!,
label: formatDateAsMMYY(dateTime),
displayTime: resultDate(dateTime),
time:
DateUtil.convertStringToDate(element.verifiedOnDateTime),
referenceValue: element.calculatedResultFlag ?? ""));
}
}
} catch (e) {}
});
}
filteredGraphValues = sortFilteredList(filteredGraphValues).reversed.toList();
notifyListeners();
}
String formatDateAsMMYY(DateTime date) {
return '${months[date.month-1]}, ${date.year}';
}
List<LabResult> sortByFlagAndValue(List<LabResult> original) {
const priorityOrder = ['LCL', 'CL', 'L', 'N', 'H', 'CH', 'HCH'];
int getFlagPriority(String? flag) {
if (flag == null) return priorityOrder.length;
final index = priorityOrder.indexOf(flag);
return index == -1 ? priorityOrder.length : index;
}
double parseResultValue(String? value) {
if (value == null) return double.nan;
return double.tryParse(value) ?? double.nan;
}
final copy = List<LabResult>.from(original);
copy.sort((a, b) {
final aFlagPriority = getFlagPriority(a.calculatedResultFlag);
final bFlagPriority = getFlagPriority(b.calculatedResultFlag);
if (aFlagPriority != bFlagPriority) {
return aFlagPriority.compareTo(bFlagPriority);
}
final aValue = parseResultValue(a.resultValue);
final bValue = parseResultValue(b.resultValue);
return aValue.compareTo(bValue);
});
return copy;
}
List<LabResult> sort(List<LabResult> original) {
DateTime? parseVerifiedDate(String? raw) {
if (raw == null) return null;
final regex = RegExp(r'\/Date\((\d+)\)\/');
final match = regex.firstMatch(raw);
if (match != null) {
final millis = int.tryParse(match.group(1)!);
if (millis != null) {
return DateTime.fromMillisecondsSinceEpoch(millis);
}
}
return null;
}
final copy = List<LabResult>.from(original);
copy.sort((a, b) {
final aDate = DateUtil.convertStringToDate(a.verifiedOnDateTime);
final bDate = DateUtil.convertStringToDate(b.verifiedOnDateTime);
final now = DateTime.now();
if (aDate == now && bDate == now) return 0;
if (aDate == now) return 1;
if (bDate == now) return -1;
return bDate.compareTo(aDate); // descending
});
return copy.toList();
}
List<DataPoint> sortFilteredList(List<DataPoint> original) {
final copy = List<DataPoint>.from(original);
copy.sort((a, b) {
final aDate =a.time;
final bDate = a.time;
final now = DateTime.now();
if (aDate == now && bDate == now) return 0;
if (aDate == now) return 1;
if (bDate == now) return -1;
return bDate.compareTo(aDate); // descending
});
return copy.toList();
}
Color getColor(String flag) {
switch (flag) {
case 'LCL':
return AppColors.criticalLowAndHigh;
case 'CL':
return AppColors.criticalLowAndHigh;
case 'L':
return AppColors.highAndLow;
case 'N':
return AppColors.bgGreenColor;
case 'H':
return AppColors.highAndLow;
case 'CH':
return AppColors.criticalLowAndHigh;
case 'HCH':
return AppColors.criticalLowAndHigh;
default:
return Colors.grey;
}
}
String getFormattedDate(DateTime date){
return DateFormat('EEEE, dd MMMM. yyyy').format(date);
}
String getAssetUrlWRTResult(String refernceValue) {
switch (refernceValue) {
case 'CL':
case 'LCL':
return AppAssets.ic_critical_low_result;
case 'L':
return AppAssets.ic_low_result;
case 'N':
return AppAssets.ic_normal_result;
case 'H':
return AppAssets.ic_low_result;
case 'CH':
case 'HCH':
return AppAssets.ic_critical_low_result;
default:
return AppAssets.ic_normal_result;
}
}
bool getRotationWRTResult(String refernceValue) {
switch (refernceValue) {
case 'CL':
case 'LCL':
case 'L':
case 'N':
return false;
case 'H':
case 'CH':
case 'HCH':
return true;
default:
return true;
}
}
}