lab result view updated for the package groups and special results

ipd-changes-for-vida-plus
taha 1 month ago
parent ce488e6954
commit 1a70d6d241

@ -18,7 +18,7 @@ pluginManagement {
plugins {
id 'dev.flutter.flutter-plugin-loader' version "1.0.0" // apply true
id "org.jetbrains.kotlin.android" version "2.0.0" apply false
id "org.jetbrains.kotlin.android" version "2.2.0" apply false
id 'com.android.application' version "8.9.0" apply false
id "com.google.gms.google-services" version "4.4.0" apply false

@ -1291,8 +1291,8 @@ const Map<String, Map<String, String>> localizedValues = {
"ar":"لا يوجد تشخيص سابق"
},
"showAttachment":{
"en":"Show\nAttachment",
"ar":"عرض\nالمرفقات"
"en":"Show Attachment",
"ar":"عرض المرفقات"
},
"selectAnAttachment":{
"en":"Select An Attachment",

@ -58,6 +58,8 @@ class AllSpecialLabResultModel {
bool? IsLabTestAttachment; // for the attachment icon in the lab result list
dynamic LabAccessionNo;
dynamic FileHash;
dynamic testDescription;
dynamic testShortDescription;
AllSpecialLabResultModel(
{this.actualDoctorRate,
@ -110,7 +112,10 @@ class AllSpecialLabResultModel {
//this.speciality,
this.status,
this.statusDesc,
this.strOrderDate});
this.strOrderDate,
this.testShortDescription,
this.testDescription,
});
AllSpecialLabResultModel.fromJson(Map<String, dynamic> json) {
actualDoctorRate = json['ActualDoctorRate'];
@ -167,6 +172,8 @@ class AllSpecialLabResultModel {
IsLabTestAttachment = json['IsLabTestAttachment'] ?? false;
LabAccessionNo = json['LabAccessionNo'] ?? json['AccessionNo'];
testDescription = json['Description'] ;
testShortDescription = json['TestShortDescription'];
if (json['FileNameWithExtensionList'] != null) {
FileNameWithExtensionList = <String>[];

@ -21,10 +21,15 @@ class LabResult {
String? verifiedOn;
dynamic verifiedOnDateTime;
bool? IsLabTestAttachment; // for the attachment icon in the lab result list
bool? IsPackage; // for the attachment icon in the lab result list
dynamic LabAccessionNo;
List<String>? FileNameWithExtensionList;
dynamic FileHash;
List<UploadedDocument>? UploadedDocuments;
String? packageName = "";
String? TestShortDescription = "";
String? PackageShortDescription = "";
LabResult(
{this.description,
@ -52,6 +57,8 @@ class LabResult {
this.LabAccessionNo,
this.FileNameWithExtensionList,
this.FileHash,
this.TestShortDescription,
this.PackageShortDescription,
this.UploadedDocuments});
LabResult.fromJson(Map<String, dynamic> json) {
@ -77,8 +84,12 @@ class LabResult {
verifiedOn = json['VerifiedOn'];
verifiedOnDateTime = json['VerifiedOnDateTime'];
IsLabTestAttachment = json['IsLabTestAttachment'] ?? false;
IsPackage = json['IsPackage'] ?? false;
LabAccessionNo = json['LabAccessionNo'] ?? json['AccessionNo'];
packageName = json['PackageName'] ??null ;
TestShortDescription = json['TestShortDescription'] ??null ;
PackageShortDescription = json['PackageShortDescription'] ??null ;
if (json['FileNameWithExtensionList'] != null) {
FileNameWithExtensionList = <String>[];

@ -12,6 +12,10 @@ class PatientLabSpecialResult {
List<UploadedDocument>? UploadedDocuments;
bool? IsLabTestAttachment; // for the attachment icon in the lab result list
dynamic LabAccessionNo;
String? testCode;
String? testDescription;
String? testID;
String? testShortDescription;
PatientLabSpecialResult(
{this.invoiceNo,
@ -21,7 +25,12 @@ class PatientLabSpecialResult {
this.resultDataTxt,
this.FileNameWithExtensionList,
this.UploadedDocuments,
this.IsLabTestAttachment});
this.IsLabTestAttachment,
this.testCode,
this.testDescription,
this.testShortDescription,
this.testID,
});
PatientLabSpecialResult.fromJson(Map<String, dynamic> json) {
SetupID = json['SetupID'];
@ -46,6 +55,11 @@ class PatientLabSpecialResult {
}
IsLabTestAttachment = json['IsLabTestAttachment'] ?? false;
testCode = json['TestCode'];
testDescription = json['Description'];
testID = json['TestID'];
testShortDescription = json['TestShortDescription'];
}
Map<String, dynamic> toJson() {

@ -60,6 +60,7 @@ class LabsService extends BaseService {
List<PatientLabSpecialResult> patientLabSpecialResult = [];
List<LabResult> labResultList = [];
Map<String, List<LabResult>> mappedLabResultList = {};
List<LabOrderResult> labOrdersResultsList = [];
List<LabAttachmentItem> labAttachment = [];
List<LabResultHistory> labOrdersResultHistoryList = [];
@ -125,11 +126,48 @@ class LabsService extends BaseService {
labResultList.add(LabResult.fromJson(lab));
});
}
///sorting the list based on the package name or test code right now if the vida3 add the package name for the doctor application endpoint then it will work cause the elements are going to give the priority to the package name if it is not null or empty otherwise it will give the priority to the test code and then it will sort the list based on the package name first then goes for the test code to sort and enjoy
mappedLabResultList = groupLabResultsByPackageName(labResultList);
}, onFailure: (String error, int statusCode) {
hasError = true;
super.error = error;
}, body: body);
}
Map<String, List<LabResult>> groupLabResultsByPackageName(List<LabResult> labResults) {
Map<String, List<LabResult>> groupedResults = {};
// Group results by package name
for (var labResult in labResults) {
String packageName = labResult.packageName?? labResult.testCode ?? 'Unknown Package';
if (groupedResults.containsKey(packageName)) {
// Package name exists, add to existing list
groupedResults[packageName]!.add(labResult);
} else {
// Package name doesn't exist, create new key with new list
groupedResults[packageName] = [labResult];
}
}
// Sort each list alphabetically by description
groupedResults.forEach((key, list) {
list.sort((a, b) {
String descA = (a.description ?? '').toLowerCase();
String descB = (b.description ?? '').toLowerCase();
return descA.compareTo(descB);
});
});
// Sort the map keys alphabetically and return a new sorted map
var sortedKeys = groupedResults.keys.toList()..sort((a, b) => a.toLowerCase().compareTo(b.toLowerCase()));
Map<String, List<LabResult>> sortedGroupedResults = {};
for (var key in sortedKeys) {
sortedGroupedResults[key] = groupedResults[key]!;
}
return sortedGroupedResults;
}
Future getPatientLabOrdersResults({PatientLabOrders? patientLabOrder, required String procedure, required PatiantInformtion patient}) async {
hasError = false;

@ -74,6 +74,7 @@ class LabsViewModel extends BaseViewModel {
List<PatientLabSpecialResult> get patientLabSpecialResult => _labsService.patientLabSpecialResult;
List<LabResult> get labResultList => _labsService.labResultList;
Map<String, List<LabResult>> get mappedLabResultList => _labsService.mappedLabResultList;
List<LabResultList> labResultLists = [];

@ -6,12 +6,10 @@ import 'package:doctor_app_flutter/core/viewModel/project_view_model.dart';
import 'package:doctor_app_flutter/core/model/patient/patiant_info_model.dart';
import 'package:doctor_app_flutter/screens/patients/profile/lab_result/laboratory_result/flow_chart_page.dart';
import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart';
import 'package:doctor_app_flutter/utils/utils.dart';
import 'package:doctor_app_flutter/widgets/shared/app_texts_widget.dart';
import 'package:doctor_app_flutter/widgets/transitions/fade_page.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:open_filex/open_filex.dart';
import 'package:provider/provider.dart';
class LabResultWidget extends StatelessWidget {
@ -24,15 +22,16 @@ class LabResultWidget extends StatelessWidget {
LabResultWidget({Key? key, required this.filterName, required this.patientLabResultList, required this.patientLabOrder, required this.patient, required this.isInpatient, required this.model})
: super(key: key);
late ProjectViewModel projectViewModel;
@override
Widget build(BuildContext context) {
projectViewModel = Provider.of(context);
Provider.of<ProjectViewModel>(context);
return Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: 8),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
// if (!isInpatient)
@ -41,234 +40,246 @@ class LabResultWidget extends StatelessWidget {
children: [
Row(
children: [
AppText(
filterName,
fontSize: SizeConfig.textMultiplier! * 2.0,
fontWeight: FontWeight.w700,
),
],
),
],
),
SizedBox(
height: 8,
),
Row(
children: [
Expanded(
child: Container(
child: Center(
Visibility(
visible: filterName.isNotEmpty,
child: AppText(
TranslationBase.of(context).description,
color: Colors.black,
fontSize: SizeConfig.textMultiplier! * 2.0,
filterName,
fontSize: SizeConfig.textMultiplier! * 1.6,
fontWeight: FontWeight.w700,
),
),
),
),
Expanded(
child: Container(
child: Center(
child: AppText(
TranslationBase.of(context).value,
color: Colors.black,
fontSize: SizeConfig.textMultiplier! * 2.0,
fontWeight: FontWeight.w700,
),
),
),
),
Expanded(
child: Container(
child: Center(
child: AppText(
TranslationBase.of(context).range,
fontSize: SizeConfig.textMultiplier! * 2.0,
fontWeight: FontWeight.w700,
),
),
),
],
),
Expanded(
child: Container(),
)
],
),
Divider(
color: Colors.grey.shade500,
thickness: 1,
),
SizedBox(
height: 12,
height: 16,
),
ListView.builder(
itemCount: patientLabResultList.length,
scrollDirection: Axis.vertical,
physics: ScrollPhysics(),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Color(0X55F2F2F2),
borderRadius: BorderRadius.all(
Radius.circular(8.0),
),
),
child: Row(
SizedBox(height: 8,),
Visibility(
visible: index == 0,
child: Column(
children: [
Expanded(
child: Container(
padding: EdgeInsets.all(10),
child: Center(
child: AppText(
patientLabResultList[index].description!,
textAlign: TextAlign.center,
fontSize: SizeConfig.textMultiplier! * 1.8,
isCopyable: true,
),
),
),
),
Expanded(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (patientLabResultList[index].checkResultStatus() != 0)
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red.shade700,
),
child: Icon(
patientLabResultList[index].checkResultStatus() == 1 ? Icons.arrow_upward : Icons.arrow_downward,
color: Colors.white,
size: 16,
),
Visibility(
visible: patientLabResultList[index].PackageShortDescription != null && patientLabResultList[index].PackageShortDescription?.isNotEmpty == true ,
child:Column(
children: [
AppText(
patientLabResultList[index].PackageShortDescription??"",
fontSize: SizeConfig.textMultiplier! * 1.3,
fontWeight: FontWeight.w400,
color: Colors.black87,
isCopyable: true,
),
Expanded(
child: Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 4),
child: Center(
child: AppText(
patientLabResultList[index].resultValue ?? "" + " " + "${patientLabResultList[index].uOM ?? ""}",
textAlign: TextAlign.center,
isCopyable: true,
fontSize: SizeConfig.textMultiplier! * 1.8,
),
),
SizedBox(
height: 8,
),
),
],
),
),
Expanded(
child: Container(
padding: EdgeInsets.all(10),
// color: Colors.white,
child: Center(
child: AppText(
patientLabResultList[index].referanceRange!,
textAlign: TextAlign.center,
fontSize: SizeConfig.textMultiplier! * 1.8,
isCopyable: true,
),
),
),
),
Expanded(
child: Column(
children: [
Visibility(
visible: patientLabResultList[index].IsLabTestAttachment ?? false,
child: InkWell(
onTap: () async {
var labAccessNumber = patientLabResultList[index].LabAccessionNo;
// if (patientLabResultList[index].FileNameWithExtensionList?.isNotEmpty == true || patientLabResultList[index].FileNameWithExtensionList?.length == 1) {
// await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, FileName: patientLabResultList[index].FileNameWithExtensionList?.first);
// model.openPDF();
// return;
// }
//
// if (patientLabResultList[index].UploadedDocuments?.isNotEmpty == true || patientLabResultList[index].UploadedDocuments?.length == 1) {
// await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, uploadedDocument: patientLabResultList[index].UploadedDocuments?.first);
// model.openPDF();
// return;
// }
showUploadedDocumentsBottomSheet(
context,
documents: patientLabResultList[index].UploadedDocuments,
fileName: patientLabResultList[index].FileNameWithExtensionList,
labAccessNumber: labAccessNumber,
projectID: int.parse(patientLabResultList[index].projectID!),
setupID: patientLabResultList[index].setupID);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AppText(
TranslationBase.of(context).showAttachment,
textDecoration: TextDecoration.underline,
color: Colors.red.shade700,
fontSize: SizeConfig.textMultiplier! * 1.2,
fontWeight: FontWeight.w700,
),
],
),
],
) ),
Visibility(
visible: (patientLabResultList.any((lab) => lab.IsLabTestAttachment ?? false)) && (patientLabResultList.any((lab) => lab.IsPackage ?? false)),
child: Center(
child: InkWell(
onTap: () async {
final labWithAttachment = patientLabResultList[index];
var labAccessNumber = labWithAttachment.LabAccessionNo;
showUploadedDocumentsBottomSheet(
context,
documents: labWithAttachment.UploadedDocuments,
fileName: labWithAttachment.FileNameWithExtensionList,
labAccessNumber: labAccessNumber,
projectID: int.parse(labWithAttachment.projectID!),
setupID: labWithAttachment.setupID,
);
},
child: Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 14, horizontal: 24),
decoration: BoxDecoration(
color: Colors.red.shade50,
borderRadius: BorderRadius.circular(16),
),
),
SizedBox(
height: 8,
),
InkWell(
onTap: () {
Navigator.push(
context,
FadePage(
page: FlowChartPage(
filterName: patientLabResultList[index].description!,
patientLabOrder: patientLabOrder,
patient: patient,
isInpatient: isInpatient,
),
),
);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.description_outlined,
color: Colors.red.shade700,
size: 20,
),
SizedBox(width: 8),
AppText(
TranslationBase.of(context).showMoreBtn,
textDecoration: TextDecoration.underline,
TranslationBase.of(context).showAttachment,
color: Colors.red.shade700,
fontSize: SizeConfig.textMultiplier! * 1.4,
fontWeight: FontWeight.w700,
),
],
),
),
],
),
),
),
SizedBox(height: 8,)
],
),
),
// Label (e.g. "Diagnosis:") - bold + underlined, like the screenshot
Row(
children: [
Expanded(
child: AppText(
patientLabResultList[index].description!,
fontSize: SizeConfig.textMultiplier! * 1.9,
color: Colors.black,
),
),
SizedBox(
width: 8,
),
// Value - plain text below the label
AppText(
(patientLabResultList[index].resultValue ?? "") + (patientLabResultList[index].uOM != null ? " ${patientLabResultList[index].uOM}" : ""),
fontSize: SizeConfig.textMultiplier! * 1.8,
fontWeight: FontWeight.w400,
color: Colors.black87,
isCopyable: true,
),
],
),
Visibility(
visible: patientLabResultList[index].TestShortDescription != null ,
child:Column(
children: [
SizedBox(
height: 20,
),
AppText(
patientLabResultList[index].TestShortDescription??"",
fontSize: SizeConfig.textMultiplier! * 1.3,
fontWeight: FontWeight.w400,
color: Colors.black87,
isCopyable: true,
),
SizedBox(
height: 8,
),
],
) ),
SizedBox(
height: 16,
),
Center(
child: InkWell(
onTap: () {
Navigator.push(
context,
FadePage(
page: FlowChartPage(
filterName: patientLabResultList.first.description!,
patientLabOrder: patientLabOrder,
patient: patient,
isInpatient: isInpatient,
),
),
);
},
child: Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 14, horizontal: 24),
decoration: BoxDecoration(
color: Colors.red.shade50,
borderRadius: BorderRadius.circular(16),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.show_chart,
color: Colors.red.shade700,
size: 20,
),
SizedBox(width: 8),
AppText(
TranslationBase.of(context).showMoreBtn,
color: Colors.red.shade700,
fontSize: SizeConfig.textMultiplier! * 1.4,
),
],
),
),
),
),
SizedBox(
height: 16,
),
Visibility(
visible: (patientLabResultList[index].IsLabTestAttachment== true ) && (patientLabResultList[index].IsPackage == false),
child: Center(
child: InkWell(
onTap: () async {
final labWithAttachment = patientLabResultList.firstWhere(
(lab) => lab.IsLabTestAttachment ?? false,
);
var labAccessNumber = labWithAttachment.LabAccessionNo;
showUploadedDocumentsBottomSheet(
context,
documents: labWithAttachment.UploadedDocuments,
fileName: labWithAttachment.FileNameWithExtensionList,
labAccessNumber: labAccessNumber,
projectID: int.parse(labWithAttachment.projectID!),
setupID: labWithAttachment.setupID,
);
},
child: Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 14, horizontal: 24),
decoration: BoxDecoration(
color: Colors.red.shade50,
borderRadius: BorderRadius.circular(16),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.description_outlined,
color: Colors.red.shade700,
size: 20,
),
SizedBox(width: 8),
AppText(
TranslationBase.of(context).showAttachment,
color: Colors.red.shade700,
fontSize: SizeConfig.textMultiplier! * 1.4,
),
],
),
),
),
),
),
],
);
}),
SizedBox(
height: 8,
),
Divider(),
],
),
);
@ -357,13 +368,13 @@ class LabResultWidget extends StatelessWidget {
}
void showUploadedDocumentsBottomSheet(
BuildContext context, {
List<UploadedDocument>? documents,
List<String>? fileName,
String? labAccessNumber,
int? projectID,
String? setupID,
}) {
BuildContext context, {
List<UploadedDocument>? documents,
List<String>? fileName,
String? labAccessNumber,
int? projectID,
String? setupID,
}) {
const double kItemHeight = 66.0; // ListTile with contentPadding: 10
final double screenHeight = MediaQuery.of(context).size.height;
final double maxSheetHeight = screenHeight * 0.5;
@ -422,7 +433,7 @@ class LabResultWidget extends StatelessWidget {
child: const Divider(height: 1, color: Colors.grey),
),
itemBuilder: (context, index) {
final docName = documents?[index]?.fileName ?? fileName?[index];
final docName = documents?[index].fileName ?? fileName?[index];
return ListTile(
contentPadding: const EdgeInsets.all(10),

@ -35,6 +35,7 @@ class LaboratoryResultWidget extends StatefulWidget {
class _LaboratoryResultWidgetState extends State<LaboratoryResultWidget> {
bool _isShowMoreGeneral = true;
bool _isShowMore = true;
int expandedIndex = 0;
late ProjectViewModel projectViewModel;
@override
@ -51,15 +52,23 @@ class _LaboratoryResultWidgetState extends State<LaboratoryResultWidget> {
baseViewModel: model,
child: SafeArea(
child: Container(
margin: EdgeInsets.all(15),
margin: EdgeInsets.all(4),
child: Column(
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
if (model.labResultLists.isNotEmpty)
if (model.mappedLabResultList.isNotEmpty)
Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(16.0),
),
),
child: Column(
children: [
InkWell(
@ -73,13 +82,13 @@ class _LaboratoryResultWidgetState extends State<LaboratoryResultWidget> {
child: Container(
padding: EdgeInsets.all(10.0),
margin: EdgeInsets.only(left: 5, right: 5),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(5.0),
),
),
// decoration: BoxDecoration(
// shape: BoxShape.rectangle,
// color: Colors.white,
// borderRadius: BorderRadius.all(
// Radius.circular(5.0),
// ),
// ),
child: Row(
children: <Widget>[
Expanded(
@ -107,33 +116,34 @@ class _LaboratoryResultWidgetState extends State<LaboratoryResultWidget> {
AnimatedContainer(
padding: EdgeInsets.all(10.0),
margin: EdgeInsets.only(left: 5, right: 5),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(5.0),
bottomRight: Radius.circular(5.0),
),
),
// decoration: BoxDecoration(
// shape: BoxShape.rectangle,
// color: Colors.white,
// borderRadius: BorderRadius.only(
// bottomLeft: Radius.circular(5.0),
// bottomRight: Radius.circular(5.0),
// ),
// ),
duration: Duration(milliseconds: 7000),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListView.builder(
itemCount: model.labResultLists.length,
scrollDirection: Axis.vertical,
physics: ScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
return LabResultWidget(
patientLabOrder: widget.patientLabOrder!,
filterName: model.labResultLists[index].filterName,
patientLabResultList: model.labResultLists[index].patientLabResultList,
patient: widget.patient!,
isInpatient: widget.isInpatient!,
model: model,
);
}),
// ListView.builder(
// itemCount: model.mappedLabResultList.length,
// scrollDirection: Axis.vertical,
// physics: ScrollPhysics(),
// shrinkWrap: true,
// itemBuilder: (context, index) {
// return LabResultWidget(
// patientLabOrder: widget.patientLabOrder!,
// filterName: model.labResultLists[index].filterName,
// patientLabResultList: model.labResultLists[index].patientLabResultList,
// patient: widget.patient!,
// isInpatient: widget.isInpatient!,
// model: model,
// );
// }),
mappedListDisplay(model)
],
),
),
@ -150,139 +160,85 @@ class _LaboratoryResultWidgetState extends State<LaboratoryResultWidget> {
height: 15,
),
if (widget.details?.isNotEmpty == true)
Column(
children: [
InkWell(
onTap: () {
setState(() {
_isShowMore = !_isShowMore;
});
},
child: Container(
padding: EdgeInsets.all(10.0),
margin: EdgeInsets.only(left: 5, right: 5),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(5.0),
)),
child: Row(
children: <Widget>[
Expanded(
child: Container(
margin: EdgeInsets.only(left: 0, right: 0),
child: AppText(
TranslationBase.of(context).specialResult,
fontSize: SizeConfig.textMultiplier! * 2.3,
bold: false,
))),
Container(
width: 25,
height: 25,
child: Icon(
_isShowMore ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
color: Colors.grey[800],
size: 22,
),
)
],
Container(
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(16.0),
)),
child: Column(
children: [
InkWell(
onTap: () {
setState(() {
_isShowMore = !_isShowMore;
});
},
child: Container(
padding: EdgeInsets.all(10.0),
margin: EdgeInsets.only(left: 5, right: 5),
child: Row(
children: <Widget>[
Expanded(
child: Container(
margin: EdgeInsets.only(left: 0, right: 0),
child: AppText(
TranslationBase.of(context).specialResult,
fontSize: SizeConfig.textMultiplier! * 2.3,
bold: false,
))),
Container(
width: 25,
height: 25,
child: Icon(
_isShowMore ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down,
color: Colors.grey[800],
size: 22,
),
)
],
),
),
),
),
if (_isShowMore)
AnimatedContainer(
padding: EdgeInsets.all(10.0),
margin: EdgeInsets.only(left: 5, right: 5),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(5.0),
bottomRight: Radius.circular(5.0),
)),
duration: Duration(milliseconds: 7000),
child: ListView.separated(
separatorBuilder: (context, index) => Divider(
color: Colors.grey[300],
thickness: 1,
),
itemCount: widget.details?.length ?? 0,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
String? resultData;
try {
resultData = (widget.details?[index])?.resultDataHTML?.toString();
} catch (_) {
resultData = null;
}
final displayData = (resultData == null || resultData.trim().isEmpty)
? TranslationBase.of(context).noDataAvailable
: resultData;
return Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
!Utils.isTextHtml(displayData)
? AppText(displayData)
: Html(data: displayData),
],
),
),
Visibility(
visible: widget.details?[index].IsLabTestAttachment ?? false,
child: InkWell(
onTap: () async {
var labAccessNumber = widget.details?[index].LabAccessionNo;
// if (widget.details?[index].FileNameWithExtensionList?.isNotEmpty == true || widget.details?[index].FileNameWithExtensionList?.length == 1) {
// await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, FileName: widget.details?[index].FileNameWithExtensionList?.first);
// model.openPDF();
// return;
// }
//
// if (widget.details?[index].UploadedDocuments?.isNotEmpty == true || widget.details?[index].UploadedDocuments?.length == 1) {
// await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, uploadedDocument: widget.details?[index].UploadedDocuments?.first);
// model.openPDF();
// return;
// }
if (_isShowMore)
AnimatedContainer(
padding: EdgeInsets.all(10.0),
margin: EdgeInsets.only(left: 5, right: 5),
// decoration: BoxDecoration(
// shape: BoxShape.rectangle,
// color: Colors.white,
// borderRadius: BorderRadius.only(
// bottomLeft: Radius.circular(5.0),
// bottomRight: Radius.circular(5.0),
// )),
duration: Duration(milliseconds: 7000),
child: ListView.separated(
separatorBuilder: (context, index) => Divider(
color: Colors.grey[300],
thickness: 1,
),
itemCount: widget.details?.length ?? 0,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
String? resultData;
try {
resultData = (widget.details?[index])?.resultDataHTML?.toString();
} catch (_) {
resultData = null;
}
final displayData = (resultData == null || resultData.trim().isEmpty)
? TranslationBase.of(context).noDataAvailable
: resultData.trim();
showUploadedDocumentsBottomSheet(
context,
model,
documents: widget.details?[index].UploadedDocuments,
fileName: widget.details?[index].FileNameWithExtensionList,
labAccessNumber: labAccessNumber,
projectID: int.parse(widget.details?[index].ProjectID??"0"),
setupID: widget.details?[index].SetupID);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AppText(
TranslationBase.of(context).showAttachment,
textDecoration: TextDecoration.underline,
color: Colors.red.shade700,
fontSize: SizeConfig.textMultiplier! * 1.2,
fontWeight: FontWeight.w700,
),
],
),
),
),
],
);
},
return buildLabDetailItem(context, index, displayData, model);
},
),
),
),
SizedBox(
height: 10,
),
],
],
),
),
],
),
@ -294,6 +250,83 @@ class _LaboratoryResultWidgetState extends State<LaboratoryResultWidget> {
),
);
}
Widget buildLabDetailItem(BuildContext context, int index, String displayData, LabsViewModel model) {
return Card(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
elevation: 8,
child: Padding(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
!Utils.isTextHtml(displayData)
? AppText(displayData)
: Html(data: displayData),
Visibility(
visible: widget.details?[index].IsLabTestAttachment ?? false,
child: Column(
children: [
SizedBox(height: 8,),
InkWell(
onTap: () async {
var labAccessNumber = widget.details?[index].LabAccessionNo;
// if (widget.details?[index].FileNameWithExtensionList?.isNotEmpty == true || widget.details?[index].FileNameWithExtensionList?.length == 1) {
// await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, FileName: widget.details?[index].FileNameWithExtensionList?.first);
// model.openPDF();
// return;
// }
//
// if (widget.details?[index].UploadedDocuments?.isNotEmpty == true || widget.details?[index].UploadedDocuments?.length == 1) {
// await model.getLabAttachments(patient, labAccessNumber: labAccessNumber, uploadedDocument: widget.details?[index].UploadedDocuments?.first);
// model.openPDF();
// return;
// }
showUploadedDocumentsBottomSheet(
context,
model,
documents: widget.details?[index].UploadedDocuments,
fileName: widget.details?[index].FileNameWithExtensionList,
labAccessNumber: labAccessNumber,
projectID: int.parse(widget.details?[index].ProjectID ?? "0"),
setupID: widget.details?[index].SetupID);
},
child: Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 14, horizontal: 24),
decoration: BoxDecoration(
color: Colors.red.shade50,
borderRadius: BorderRadius.circular(16),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.description_outlined,
color: Colors.red.shade700,
size: 20,
),
SizedBox(width: 8),
AppText(
TranslationBase.of(context).showAttachment,
color: Colors.red.shade700,
fontSize: SizeConfig.textMultiplier! * 1.4,
),
],
),
),
),
],
),
),
],
),
),
);
}
void showUploadedDocumentsBottomSheet(
BuildContext context, LabsViewModel model, {
@ -361,7 +394,7 @@ class _LaboratoryResultWidgetState extends State<LaboratoryResultWidget> {
child: const Divider(height: 1, color: Colors.grey),
),
itemBuilder: (context, index) {
final docName = documents?[index]?.fileName ?? fileName?[index];
final docName = documents?[index].fileName ?? fileName?[index];
return ListTile(
contentPadding: const EdgeInsets.all(10),
@ -403,4 +436,104 @@ class _LaboratoryResultWidgetState extends State<LaboratoryResultWidget> {
},
);
}
mappedListDisplay(LabsViewModel model) {
final packageEntries = model.mappedLabResultList.entries.toList();
return ListView.separated(
separatorBuilder: (_, __) => Padding(padding: EdgeInsets.all(4),
child: Divider(
height: 2,
) ,),
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.zero,
shrinkWrap: true,
itemCount: packageEntries.length,
itemBuilder: (context, packageIndex) {
final packageName = packageEntries[packageIndex].key;
final labResults = packageEntries[packageIndex].value;
final isExpanded = expandedIndex == packageIndex;
return InkWell(
onTap: () {
setState(() {
if (isExpanded) {
expandedIndex = -1; // Collapse if already expanded
} else
expandedIndex = packageIndex;
});
},
child: Card(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
children: <Widget>[
Expanded(
child: Container(
margin: EdgeInsets.only(left: 0, right: 0),
child: AppText(
packageName,
fontSize: SizeConfig.textMultiplier! * 1.8,
bold: false,
))),
// Arrow rotates smoothly between down/up instead of snapping
AnimatedRotation(
turns: isExpanded ? 0.5 : 0.0,
duration: const Duration(milliseconds: 250),
curve: Curves.easeInOut,
child: Container(
width: 25,
height: 25,
child: Icon(
Icons.keyboard_arrow_down,
color: Colors.grey[800],
size: 22,
),
),
)
],
),
// Animated expand/collapse of the lab result content
AnimatedSize(
duration: const Duration(milliseconds: 250),
curve: Curves.easeInOut,
alignment: Alignment.topCenter,
child: AnimatedCrossFade(
duration: const Duration(milliseconds: 250),
sizeCurve: Curves.easeInOut,
firstCurve: Curves.easeIn,
secondCurve: Curves.easeIn,
crossFadeState: isExpanded ? CrossFadeState.showSecond : CrossFadeState.showFirst,
firstChild: const SizedBox(width: double.infinity, height: 0),
secondChild: Column(
mainAxisSize: MainAxisSize.min,
children: [
LabResultWidget(
patientLabOrder: widget.patientLabOrder!,
filterName: "",
patientLabResultList: labResults,
patient: widget.patient!,
isInpatient: widget.isInpatient!,
model: model,
),
],
),
),
),
],
),
),
),
);
},
);
}
}

@ -3,6 +3,7 @@ import 'package:doctor_app_flutter/core/viewModel/PatientMedicalReportViewModel.
import 'package:doctor_app_flutter/core/model/patient/patiant_info_model.dart';
import 'package:doctor_app_flutter/core/viewModel/labs_view_model.dart';
import 'package:doctor_app_flutter/screens/base/base_view.dart';
import 'package:doctor_app_flutter/utils/extenstions_utils.dart';
import 'package:doctor_app_flutter/utils/translations_delegate_base_utils.dart';
import 'package:doctor_app_flutter/widgets/patients/profile/app_bar/patient-profile-app-bar.dart';
import 'package:doctor_app_flutter/widgets/patients/patient_service_title.dart';
@ -52,29 +53,68 @@ class SpecialLabResultDetailsPage extends StatelessWidget {
child: Column(
children: [
(resultData != null && resultData.isNotEmpty)
? Container(
width: double.infinity,
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.all(Radius.circular(8)),
border: Border.fromBorderSide(
BorderSide(
color: Colors.white,
width: 1.0,
),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Html(data: resultData ?? ""),
HtmlWidget(resultData ?? ""),
Visibility(
visible: labResult.IsLabTestAttachment ?? false,
child: InkWell(
? Card(
color: Colors.white,
margin: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
),
elevation: 4,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Visibility(
visible: labResult.testDescription != null && (labResult.testDescription as String).isNotEmpty ,
child:Column(
children: [
SizedBox(
height: 8,
),
AppText(
labResult.testDescription ??"",
fontSize: SizeConfig.textMultiplier! * 1.6,
fontWeight: FontWeight.w700,
color: Colors.black87,
isCopyable: true,
),
SizedBox(
height: 8,
),
],
) ),
Visibility(
visible: labResult.testShortDescription != null && (labResult.testShortDescription as String).isNotEmpty ,
child:Column(
children: [
SizedBox(
height: 8,
),
AppText(
labResult.testShortDescription ??"",
fontSize: SizeConfig.textMultiplier! * 1.3,
fontWeight: FontWeight.w400,
color: Colors.black87,
isCopyable: true,
),
SizedBox(
height: 8,
),
],
) ),
// Html(data: resultData ?? ""),
HtmlWidget(resultData ?? ""),
Visibility(
visible: labResult.IsLabTestAttachment ?? false,
child: Column(
children: [
SizedBox(
height: 12,
),
InkWell(
onTap: () async {
var labAccessNumber = labResult.LabAccessionNo;
// if (patientLabResultList[index].FileNameWithExtensionList?.isNotEmpty == true || patientLabResultList[index].FileNameWithExtensionList?.length == 1) {
@ -89,32 +129,49 @@ class SpecialLabResultDetailsPage extends StatelessWidget {
// return;
// }
showUploadedDocumentsBottomSheet(context,
documents: labResult.UploadedDocuments,
fileName: labResult.FileNameWithExtensionList,
labAccessNumber: labAccessNumber,
projectID: int.parse(labResult.projectID!),
// projectID: 160,
setupID: labResult.setupID,
model: model);
},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AppText(
TranslationBase
.of(context)
.showAttachment,
textDecoration: TextDecoration.underline,
color: Colors.red.shade700,
fontSize: SizeConfig.textMultiplier! * 1.2,
fontWeight: FontWeight.w700,
showUploadedDocumentsBottomSheet(
context,
documents: labResult.UploadedDocuments,
fileName: labResult.FileNameWithExtensionList,
labAccessNumber: labAccessNumber,
projectID: int.parse(labResult.projectID!),
// projectID: 160,
setupID: labResult.setupID,
model: model,
);
},
child: Container(
width: double.infinity,
padding: EdgeInsets.symmetric(vertical: 14, horizontal: 16),
decoration: BoxDecoration(
color: Colors.red.shade50,
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.description_outlined,
color: Colors.red.shade700,
size: 18,
),
SizedBox(width: 6),
AppText(
TranslationBase.of(context).showAttachment,
color: Colors.red.shade700,
fontSize: SizeConfig.textMultiplier! * 1.4,
fontWeight: FontWeight.w400,
),
],
),
),
),
],
),
),
),
],
],
),
),
)
: Container(

Loading…
Cancel
Save