import ' dart:collection ' ;
import ' dart:convert ' ;
import ' dart:core ' ;
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/dependencies.dart ' ;
import ' package:hmg_patient_app_new/core/utils/date_util.dart ' ;
import ' package:hmg_patient_app_new/core/utils/loading_utils.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/ai_overview_labresult_model_payload.dart ' ;
import ' package:hmg_patient_app_new/features/lab/models/resp_models/ai_overview_labresults_by_ai_model.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_order_response_by_ai_model.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_result_via_clinic/LabResultByClinic.dart ' ;
import ' package:hmg_patient_app_new/presentation/lab/lab_results/lab_result_details.dart ' ;
import ' package:hmg_patient_app_new/presentation/lab/lab_result_via_clinic/lab_ai_analysis_detailed_page.dart ' ;
import ' package:hmg_patient_app_new/services/cache_service.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:hmg_patient_app_new/widgets/routes/custom_page_route.dart ' ;
import ' package:intl/intl.dart ' show DateFormat ;
class LabViewModel extends ChangeNotifier {
bool isLabOrdersLoading = false ;
bool isLabResultsLoading = false ;
bool isLabResultByHospitalLoading = false ;
bool isSpecialResultsLoading = false ;
bool isGraphVisible = true ;
bool shouldShowGraph = true ;
bool isLabNeedToLoad = true ;
LabRepo labRepo ;
ErrorHandlerService errorHandlerService ;
NavigationService navigationService ;
List < PatientLabOrdersResponseModel > patientLabOrders = [ ] ;
List < PatientLabOrdersResponseModel > filteredLabOrders = [ ] ;
List < PatientLabOrdersResponseModel > tempLabOrdersList = [ ] ;
String labSpecialResult = " " ;
List < String > labOrderTests = [ ] ;
String patientLabResultReportPDFBase64 = " " ;
String ? flagForHighReferenceRange ;
double highRefrenceValue = double . negativeInfinity ;
double lowRefenceValue = double . infinity ;
double highTransformedReferenceValue = double . negativeInfinity ;
double lowTransformedReferenceValue = double . infinity ;
String ? flagForLowReferenceRange ;
PatientLabOrdersResponseModel ? currentlySelectedPatientOrder ;
List < LabResult > mainLabResultsByHospitals = [ ] ;
List < LabResult > mainLabResults = [ ] ;
List < DataPoint > mainGraphPoints = [ ] ;
List < DataPoint > filteredGraphValues = [ ] ;
List months = [ ' Jan ' , ' Feb ' , ' Mar ' , ' April ' , ' May ' , ' Jun ' , ' July ' , ' Aug ' , ' Sep ' , ' Oct ' , ' Nov ' , ' Dec ' ] ;
late List < String > _labSuggestionsList = [ ] ;
List < String > get labSuggestions = > _labSuggestionsList ;
Set < TestDetails > uniqueTests = { } ;
List < TestDetails > uniqueTestsList = [ ] ;
List < String > indexedCharacterForUniqueTest = [ ] ;
double maxY = 0.0 ;
double minY = double . infinity ;
double maxX = double . infinity ;
// --- New grouping fields ---
bool isSortByClinic = true ;
List < List < PatientLabOrdersResponseModel > > patientLabOrdersByClinic = [ ] ;
List < List < PatientLabOrdersResponseModel > > patientLabOrdersByHospital = [ ] ;
List < List < PatientLabOrdersResponseModel > > patientLabOrdersViewList = [ ] ;
LabOrderResponseByAi ? labOrderResponseByAi ;
LabOrdersResponseByAi ? labOrdersResponseByAi ;
LabViewModel ( { required this . labRepo , required this . errorHandlerService , required this . navigationService } ) ;
initLabProvider ( ) {
// if (isLabNeedToLoad) {
patientLabOrders . clear ( ) ;
filteredLabOrders . clear ( ) ;
labOrderTests . clear ( ) ;
isLabOrdersLoading = true ;
isLabResultsLoading = true ;
patientLabOrdersByClinic . clear ( ) ;
patientLabOrdersByHospital . clear ( ) ;
patientLabOrdersViewList . clear ( ) ;
getPatientLabOrders ( ) ;
// }
notifyListeners ( ) ;
}
setIsLabNeedToLoad ( bool value ) {
isLabNeedToLoad = value ;
notifyListeners ( ) ;
}
void setIsSortByClinic ( bool value ) {
isSortByClinic = value ;
patientLabOrdersViewList = isSortByClinic ? patientLabOrdersByClinic : patientLabOrdersByHospital ;
notifyListeners ( ) ;
}
Future < void > getPatientLabOrders ( { Function ( dynamic ) ? onSuccess , Function ( String ) ? onError } ) async {
// if (!isLabNeedToLoad) return;
isLabOrdersLoading = true ;
patientLabOrders . clear ( ) ;
uniqueTests . clear ( ) ;
labOrderTests . clear ( ) ;
uniqueTests = { } ;
patientLabOrdersByClinic . clear ( ) ;
patientLabOrdersByHospital . clear ( ) ;
patientLabOrdersViewList . clear ( ) ;
notifyListeners ( ) ;
final result = await labRepo . getPatientLabOrders ( ) ;
result . fold (
( failure ) async {
isLabOrdersLoading = false ;
isLabResultsLoading = false ;
notifyListeners ( ) ;
} ,
// => await errorHandler_service.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 ;
// --- Build groups by clinic and by hospital (projectName) ---
final clinicMap = < String , List < PatientLabOrdersResponseModel > > { } ;
final hospitalMap = < String , List < PatientLabOrdersResponseModel > > { } ;
for ( var order in patientLabOrders ) {
final clinicKey = ( order . clinicDescription ? ? ' Unknown ' ) . trim ( ) ;
clinicMap . putIfAbsent ( clinicKey , ( ) = > [ ] ) . add ( order ) ;
final hospitalKey = ( order . projectName ? ? order . projectID ? ? ' Unknown ' ) . toString ( ) . trim ( ) ;
hospitalMap . putIfAbsent ( hospitalKey , ( ) = > [ ] ) . add ( order ) ;
}
patientLabOrdersByClinic = clinicMap . values . toList ( ) ;
patientLabOrdersByHospital = hospitalMap . values . toList ( ) ;
patientLabOrdersViewList = isSortByClinic ? patientLabOrdersByClinic : patientLabOrdersByHospital ;
filterSuggestions ( ) ;
getUniqueTestDescription ( ) ;
isLabNeedToLoad = false ;
notifyListeners ( ) ;
if ( onSuccess ! = null ) {
onSuccess ( apiResponse ) ;
}
}
} ,
) ;
}
Future < void > getLabResultReportPDF ( { required PatientLabOrdersResponseModel labOrder , Function ( dynamic ) ? onSuccess , Function ( String ) ? onError } ) async {
final result = await labRepo . getLabResultReportPDF ( labOrder: labOrder ) ;
result . fold (
( failure ) async = > await errorHandlerService . handleError (
failure: failure ,
onOkPressed: ( ) {
onError ! ( failure . message ) ;
} ,
) ,
( apiResponse ) {
if ( apiResponse . messageStatus = = 2 ) {
onError ! ( apiResponse . errorMessage ! ) ;
// dialogService.showErrorDialog(message: apiResponse.errorMessage!, onOkPressed: () {});
} else if ( apiResponse . messageStatus = = 1 ) {
patientLabResultReportPDFBase64 = apiResponse . data ! ;
notifyListeners ( ) ;
if ( onSuccess ! = null ) {
onSuccess ( apiResponse ) ;
}
}
} ,
) ;
}
filterSuggestions ( ) {
final List < String > labels = patientLabOrders . expand ( ( order ) = > order . testDetails ? ? [ ] ) . map ( ( detail ) = > detail . description ) . whereType < String > ( ) . 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 ;
}
notifyListeners ( ) ;
}
getUniqueTestDescription ( ) {
uniqueTests = {
for ( var item in patientLabOrders )
if ( item . testDetails ! = null )
. . . ? item . testDetails ? . map < TestDetails > ( ( test ) = > TestDetails (
testDescriptionEn: test . testDescriptionEn . toString ( ) ,
testDescriptionAr: test . testDescriptionAr . toString ( ) ,
description: test . description . toString ( ) ,
testCode: test . testCode . toString ( ) ,
testID: test . testID ,
createdOn: item . createdOn ,
model: item ) )
} ;
uniqueTestsList = uniqueTests . toList ( ) ;
uniqueTestsList = Utils . uniqueBy ( uniqueTestsList , ( p ) = > p . testCode ) ;
uniqueTestsList . sort ( ( a , b ) {
return a . description ! . toLowerCase ( ) . compareTo ( b . description ! . toLowerCase ( ) ) ;
} ) ;
indexedCharacterForUniqueTest . clear ( ) ;
for ( var test in uniqueTestsList ) {
String label = test . description ? ? " " ;
if ( label . isEmpty ) continue ;
if ( indexedCharacterForUniqueTest . contains ( label [ 0 ] . toLowerCase ( ) ) ) continue ;
indexedCharacterForUniqueTest . add ( label [ 0 ] . toLowerCase ( ) ) ;
}
for ( var element in uniqueTests ) {
labOrderTests . add ( element . description ? ? " " ) ;
}
}
Future < void > getLabResultsByAppointmentNo (
{ required num appointmentNo ,
required num projectID ,
required num clinicID ,
required int doctorID ,
required String clinicName ,
required String doctorName ,
required String projectName ,
required String appointmentDate ,
Function ( dynamic ) ? onSuccess ,
Function ( String ) ? onError } ) async {
bool isVidaPlus = Utils . isVidaPlusProject ( projectID . toInt ( ) ) ;
final result = await labRepo . getLabResultsByAppointmentNo ( appointmentNo: appointmentNo , projectID: projectID , clinicID: clinicID ) ;
result . fold (
( failure ) async {
// await errorHandlerService.handleError(failure: failure);
if ( onError ! = null ) {
onError ( failure . message ) ;
}
} ,
( apiResponse ) {
if ( apiResponse . messageStatus = = 2 ) {
if ( onError ! = null ) {
onError ( apiResponse . errorMessage ! ) ;
}
} else if ( apiResponse . messageStatus = = 1 ) {
if ( apiResponse . data ! = null & & apiResponse . data ! . isNotEmpty ) {
PatientLabOrdersResponseModel labOrder = PatientLabOrdersResponseModel ( ) ;
labOrder . invoiceNoVP = isVidaPlus ? apiResponse . data [ 0 ] [ ' InvoiceNo ' ] . toString ( ) : " 0 " ;
labOrder . invoiceNo = isVidaPlus ? " 0 " : apiResponse . data [ 0 ] [ ' InvoiceNo ' ] . toString ( ) ;
labOrder . orderNo = apiResponse . data [ 0 ] [ ' OrderNo ' ] . toString ( ) ;
labOrder . invoiceType = apiResponse . data [ 0 ] [ ' InvoiceType ' ] . toString ( ) ;
labOrder . setupID = apiResponse . data [ 0 ] [ ' SetupID ' ] . toString ( ) ;
labOrder . projectID = projectID . toString ( ) ;
labOrder . clinicID = clinicID . toInt ( ) ;
labOrder . doctorID = doctorID ;
labOrder . clinicDescription = clinicName ;
labOrder . doctorName = doctorName ;
labOrder . projectName = projectName ;
labOrder . orderDate = appointmentDate ;
currentlySelectedPatientOrder = labOrder ;
getPatientLabResultByHospital ( labOrder ) ;
getPatientSpecialResult ( labOrder ) ;
if ( onSuccess ! = null ) {
onSuccess ( apiResponse ) ;
}
navigationService . push (
CustomPageRoute (
page: LabResultByClinic ( labOrder: labOrder ) ,
) ,
) ;
} else { }
notifyListeners ( ) ;
}
} ,
) ;
}
Future < void > getPatientLabResultByHospital ( PatientLabOrdersResponseModel laborder ) async {
isLabResultByHospitalLoading = true ;
notifyListeners ( ) ;
mainLabResultsByHospitals . clear ( ) ;
final result = await labRepo . getPatientLabResultsByHospitals ( laborder , Utils . isVidaPlusProject ( int . parse ( laborder . projectID ? ? " 0 " ) ) ) ;
result . fold (
( failure ) async {
isLabResultByHospitalLoading = false ;
notifyListeners ( ) ;
// await errorHandlerService.handleError(failure: failure);
} ,
( apiResponse ) {
isLabResultByHospitalLoading = false ;
if ( apiResponse . messageStatus = = 2 ) {
} else if ( apiResponse . messageStatus = = 1 ) {
mainLabResultsByHospitals = apiResponse . data ? ? [ ] ;
notifyListeners ( ) ;
}
} ,
) ;
}
Future < void > getPatientLabResult ( PatientLabOrdersResponseModel laborder , String procedureName , String testDescription , String unitOfMeasure ) async {
LoaderBottomSheet . showLoader ( ) ;
mainLabResults . clear ( ) ;
filteredGraphValues . clear ( ) ;
maxY = double . negativeInfinity ;
minY = double . infinity ;
maxX = double . infinity ;
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 recentThree = sort ( apiResponse . data ! ) ;
mainLabResults = recentThree ;
double highRefrenceValue = double . negativeInfinity ;
String ? flagForHighReferenceRange ;
double lowRefenceValue = double . infinity ;
String ? flagForLowReferenceRange ;
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 ;
}
if ( resultValue < minY ) {
minY = resultValue ;
}
if ( highRefrenceValue < double . parse ( element . referenceHigh ? ? " 0.0 " ) ) {
highRefrenceValue = double . parse ( element . referenceHigh ? ? " 0.0 " ) ;
flagForHighReferenceRange = element . calculatedResultFlag ;
}
if ( lowRefenceValue > double . parse ( element . referenceLow ? ? " 0.0 " ) ) {
lowRefenceValue = double . parse ( element . referenceLow ? ? " 0.0 " ) ;
flagForLowReferenceRange = element . calculatedResultFlag ;
}
filteredGraphValues . add ( DataPoint (
value: transformedValue ,
actualValue: element . resultValue ! ,
label: formatDateAsMMYY ( dateTime ) ,
unitOfMeasurement: element . uOM ,
displayTime: resultDate ( dateTime ) ,
time: DateUtil . convertStringToDate ( element . verifiedOnDateTime ) ,
referenceValue: element . calculatedResultFlag ? ? " " ,
) ) ;
} catch ( e ) { }
} ) ;
if ( flagForLowReferenceRange = = null & & flagForHighReferenceRange = = null ) {
highRefrenceValue = maxY ;
lowRefenceValue = minY ;
}
if ( minY > lowRefenceValue ) {
minY = lowRefenceValue - 25 ;
}
this . flagForHighReferenceRange = flagForHighReferenceRange ;
this . flagForLowReferenceRange = flagForLowReferenceRange ;
highTransformedReferenceValue = double . parse ( transformValueInRange ( highRefrenceValue , flagForHighReferenceRange ? ? " " ) . toStringAsFixed ( 1 ) ) ;
lowTransformedReferenceValue = double . parse ( transformValueInRange ( lowRefenceValue , flagForLowReferenceRange ? ? " " ) . toStringAsFixed ( 1 ) ) ;
this . highRefrenceValue = double . parse ( highRefrenceValue . toStringAsFixed ( 1 ) ) ;
this . lowRefenceValue = double . parse ( lowRefenceValue . toStringAsFixed ( 1 ) ) ;
if ( maxY < highRefrenceValue ) {
maxY = highRefrenceValue ;
}
maxY + = 25 ;
minY - = 25 ;
LabResult recentResult = recentThree . first ;
recentResult . uOM = unitOfMeasure ;
checkIfGraphShouldBeDisplayed ( recentResult ) ;
recentResult . verifiedOn = resultDate ( DateUtil . convertStringToDate ( recentResult . verifiedOnDateTime ! ) ) ;
// filteredGraphValues = [filteredGraphValues.first];
labOrderResponseByAi = null ;
navigationService . push (
MaterialPageRoute (
builder: ( _ ) = > LabResultDetails ( recentLabResult: recentResult , testDescription: testDescription ) ,
) ,
) ;
notifyListeners ( ) ;
}
} ,
) ;
}
void checkIfGraphShouldBeDisplayed ( LabResult recentResult ) {
shouldShowGraph = recentResult . checkIfGraphShouldBeDisplayed ( ) ;
isGraphVisible = shouldShowGraph ;
notifyListeners ( ) ;
}
Future < void > getPatientSpecialResult ( PatientLabOrdersResponseModel laborder ) async {
isSpecialResultsLoading = true ;
labSpecialResult = " " ;
notifyListeners ( ) ;
final result = await labRepo . getSpecialLabResult (
laborder ,
Utils . isVidaPlusProject ( int . parse ( laborder . projectID ? ? " 0 " ) ) ,
) ;
result . fold (
( failure ) async {
isSpecialResultsLoading = false ;
notifyListeners ( ) ;
// await errorHandlerService.handleError(failure: failure);
} ,
( apiResponse ) {
isSpecialResultsLoading = false ;
if ( apiResponse . messageStatus = = 2 ) {
} else if ( apiResponse . messageStatus = = 1 ) {
StringBuffer htmlbuffer = StringBuffer ( " " ) ;
apiResponse . data ? . forEach ( ( element ) {
if ( element . resultDataHTML ! = null & & element . resultDataHTML ? . isNotEmpty = = true ) htmlbuffer . write ( " ${ element . resultDataHTML } <br/> <br/> " ) ;
} ) ;
labSpecialResult = htmlbuffer . toString ( ) ;
notifyListeners ( ) ;
}
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 ) ,
unitOfMeasurement: element . uOM ,
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 ! ,
unitOfMeasurement: element . uOM ,
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 ) ,
unitOfMeasurement: element . uOM ,
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 ) {
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 = b . 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 ;
}
}
String getSeverityText ( String refernceValue ) {
switch ( refernceValue ) {
case ' N ' :
return " normal " ;
case ' L ' :
case ' H ' :
return " monitor " ;
case ' CL ' :
case ' LCL ' :
case ' CH ' :
case ' HCH ' :
return " attention " ;
default :
return " normal " ;
}
}
alterGraphVisibility ( ) {
isGraphVisible = ! isGraphVisible ;
notifyListeners ( ) ;
}
Future < void > getAiOverviewLabOrders ( { required PatientLabOrdersResponseModel labOrder , required String loadingText } ) async {
// LoadingUtils.showFullScreenLoader(loadingText: "Loading and analysing your data,\nPlease be patient and let the AI do the magic. \nPlease be patient, This might take some time.");
LoadingUtils . showFullScreenLoader ( loadingText: loadingText ) ;
List < Map < String , dynamic > > results = [ ] ;
Map < String , dynamic > orderData = { " order_date " : labOrder . orderDate ? ? " " , " clinic " : labOrder . clinicDescription ? ? " " , " doctor " : labOrder . doctorName ? ? " " , " results " : [ ] } ;
List < Map < String , dynamic > > testResults = [ ] ;
if ( labOrder . testDetails ! = null & & labOrder . testDetails ! . isNotEmpty ) {
for ( var testDetail in labOrder . testDetails ! ) {
LabResult ? matchingResult =
mainLabResultsByHospitals . firstWhere ( ( labResult ) = > labResult . testCode = = testDetail . testCode | | labResult . description = = testDetail . description , orElse: ( ) = > LabResult ( ) ) ;
testResults . add ( {
" test_name " : testDetail . description ? ? " " ,
" result_value " : matchingResult . resultValue ? ? " " ,
" reference_range " : matchingResult . referanceRange ? ? " " ,
" unit " : matchingResult . uOM ? ? " " ,
" flag " : matchingResult . calculatedResultFlag ? ? " N "
} ) ;
}
}
orderData [ " results " ] = testResults ;
results . add ( orderData ) ;
final result = await labRepo . getPatientAiOverViewLabOrders ( results ) ;
result . fold (
( failure ) async {
LoadingUtils . hideFullScreenLoader ( ) ;
await errorHandlerService . handleError ( failure: failure ) ;
} ,
( apiResponse ) {
LoadingUtils . hideFullScreenLoader ( ) ;
if ( apiResponse . messageStatus = = 2 ) {
} else if ( apiResponse . messageStatus = = 1 ) {
labOrdersResponseByAi = apiResponse . data ;
navigationService . push (
MaterialPageRoute ( builder: ( _ ) = > LabAiAnalysisDetailedPage ( ) ) ,
) ;
}
} ,
) ;
LoadingUtils . hideFullScreenLoader ( ) ;
}
Future < void > getAiOverviewSingleLabResult ( { required String langId , required LabResult recentLabResult , required String loadingText } ) async {
LoaderBottomSheet . showLoader ( loadingText: loadingText ) ;
List < Map < String , dynamic > > results = [ ] ;
results . add ( {
" Description " : recentLabResult . description ? ? ' ' ,
" ResultValue " : recentLabResult . resultValue ? ? ' ' ,
" CalculatedResultFlag " : recentLabResult . calculatedResultFlag ? ? ' ' ,
" UOM " : recentLabResult . uOM ? ? ' ' ,
" ReferanceRange " : recentLabResult . referanceRange ? ? ' ' ,
} ) ;
var payload = { " patient_id " : currentlySelectedPatientOrder ! . patientID , " language_id " : langId , " lab_results " : results } ;
final result = await labRepo . getPatientAiOverViewLabOrder ( payload ) ;
result . fold (
( failure ) async {
LoaderBottomSheet . hideLoader ( ) ;
await errorHandlerService . handleError ( failure: failure ) ;
} ,
( apiResponse ) {
LoaderBottomSheet . hideLoader ( ) ;
if ( apiResponse . messageStatus = = 2 ) {
} else if ( apiResponse . messageStatus = = 1 ) {
labOrderResponseByAi = apiResponse . data ;
notifyListeners ( ) ;
}
} ,
) ;
LoaderBottomSheet . hideLoader ( ) ;
}
}