commit
ba0a2a2a58
@ -0,0 +1,79 @@
|
||||
class PrescriptionAnalysisResponse {
|
||||
String? prescriptionSummary;
|
||||
List<MedicineAnalysis>? medicinesAnalysis;
|
||||
List<String>? importantWarnings;
|
||||
List<String>? medicineInteractions;
|
||||
String? followUpNeeded;
|
||||
int? languageId;
|
||||
|
||||
PrescriptionAnalysisResponse({
|
||||
this.prescriptionSummary,
|
||||
this.medicinesAnalysis,
|
||||
this.importantWarnings,
|
||||
this.medicineInteractions,
|
||||
this.followUpNeeded,
|
||||
this.languageId,
|
||||
});
|
||||
|
||||
PrescriptionAnalysisResponse.fromJson(Map<String, dynamic> json) {
|
||||
prescriptionSummary = json['prescription_summary'];
|
||||
if (json['medicines_analysis'] != null) {
|
||||
medicinesAnalysis = <MedicineAnalysis>[];
|
||||
json['medicines_analysis'].forEach((v) {
|
||||
medicinesAnalysis!.add(MedicineAnalysis.fromJson(v));
|
||||
});
|
||||
}
|
||||
importantWarnings = json['important_warnings'] != null ? json['important_warnings'].cast<String>() : [];
|
||||
medicineInteractions = json['medicine_interactions'] != null ? json['medicine_interactions'].cast<String>() : [];
|
||||
followUpNeeded = json['follow_up_needed'];
|
||||
languageId = json['language_id'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['prescription_summary'] = prescriptionSummary;
|
||||
if (medicinesAnalysis != null) {
|
||||
data['medicines_analysis'] = medicinesAnalysis!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['important_warnings'] = importantWarnings;
|
||||
data['medicine_interactions'] = medicineInteractions;
|
||||
data['follow_up_needed'] = followUpNeeded;
|
||||
data['language_id'] = languageId;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class MedicineAnalysis {
|
||||
String? medicineName;
|
||||
String? benefit;
|
||||
List<String>? commonSideEffects;
|
||||
List<String>? seriousWarnings;
|
||||
String? storage;
|
||||
|
||||
MedicineAnalysis({
|
||||
this.medicineName,
|
||||
this.benefit,
|
||||
this.commonSideEffects,
|
||||
this.seriousWarnings,
|
||||
this.storage,
|
||||
});
|
||||
|
||||
MedicineAnalysis.fromJson(Map<String, dynamic> json) {
|
||||
medicineName = json['medicine_name'];
|
||||
benefit = json['benefit'];
|
||||
commonSideEffects = json['common_side_effects'] != null ? json['common_side_effects'].cast<String>() : [];
|
||||
seriousWarnings = json['serious_warnings'] != null ? json['serious_warnings'].cast<String>() : [];
|
||||
storage = json['storage'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['medicine_name'] = medicineName;
|
||||
data['benefit'] = benefit;
|
||||
data['common_side_effects'] = commonSideEffects;
|
||||
data['serious_warnings'] = seriousWarnings;
|
||||
data['storage'] = storage;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,310 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hmg_patient_app_new/core/app_assets.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/size_utils.dart';
|
||||
import 'package:hmg_patient_app_new/core/utils/utils.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/string_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/extensions/widget_extensions.dart';
|
||||
import 'package:hmg_patient_app_new/features/prescriptions/models/resp_models/prescription_analysis_response_model.dart';
|
||||
import 'package:hmg_patient_app_new/features/prescriptions/prescriptions_view_model.dart';
|
||||
import 'package:hmg_patient_app_new/generated/locale_keys.g.dart';
|
||||
import 'package:hmg_patient_app_new/theme/colors.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/appbar/collapsing_list_view.dart';
|
||||
import 'package:hmg_patient_app_new/widgets/expandable_list_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class PrescriptionAiAnalysisDetailedPage extends StatefulWidget {
|
||||
const PrescriptionAiAnalysisDetailedPage({super.key});
|
||||
|
||||
@override
|
||||
State<PrescriptionAiAnalysisDetailedPage> createState() => _PrescriptionAiAnalysisDetailedPageState();
|
||||
}
|
||||
|
||||
class _PrescriptionAiAnalysisDetailedPageState extends State<PrescriptionAiAnalysisDetailedPage> {
|
||||
late PrescriptionsViewModel prescriptionsViewModel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
prescriptionsViewModel = Provider.of<PrescriptionsViewModel>(context, listen: false);
|
||||
return CollapsingListView(
|
||||
isClose: true,
|
||||
title: LocaleKeys.aiAnalysis.tr(context: context),
|
||||
child: Consumer<PrescriptionsViewModel>(
|
||||
builder: (context, model, child) {
|
||||
if (model.prescriptionAnalysisResponse == null) {
|
||||
return Utils.getNoDataWidget(context);
|
||||
}
|
||||
|
||||
final analysis = model.prescriptionAnalysisResponse!;
|
||||
List<ExpandableListItem> expandableItems = [];
|
||||
|
||||
// Summary Section
|
||||
if (analysis.prescriptionSummary != null && analysis.prescriptionSummary!.isNotEmpty) {
|
||||
expandableItems.add(
|
||||
ExpandableListItem(
|
||||
backgroundColor: Colors.transparent,
|
||||
expandedBackgroundColor: Colors.transparent,
|
||||
title: LocaleKeys.summary.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor),
|
||||
initiallyExpanded: true,
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 12.r,
|
||||
side: BorderSide(width: 1, color: Color(0xFF0B85F7)),
|
||||
),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: (analysis.prescriptionSummary ?? "").toText14(color: AppColors.textColorLight, height: 1.5, weight: FontWeight.w400),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Medicines Analysis Section
|
||||
if (analysis.medicinesAnalysis != null && analysis.medicinesAnalysis!.isNotEmpty) {
|
||||
expandableItems.add(
|
||||
ExpandableListItem(
|
||||
backgroundColor: Colors.transparent,
|
||||
expandedBackgroundColor: Colors.transparent,
|
||||
title: LocaleKeys.medicinesAnalysis.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor),
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
...analysis.medicinesAnalysis!.map((medicine) {
|
||||
return Column(
|
||||
children: [
|
||||
_buildMedicineCard(medicine),
|
||||
SizedBox(height: 16.h),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Important Warnings Section
|
||||
if (analysis.importantWarnings != null && analysis.importantWarnings!.isNotEmpty) {
|
||||
expandableItems.add(
|
||||
ExpandableListItem(
|
||||
backgroundColor: Colors.transparent,
|
||||
expandedBackgroundColor: Colors.transparent,
|
||||
title: LocaleKeys.importantWarnings.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor),
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 12.r,
|
||||
side: BorderSide(width: 1, color: Color(0xFFFF5252)),
|
||||
),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: analysis.importantWarnings!.map((warning) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 8.h),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(Icons.warning_amber_rounded, color: Color(0xFFFF5252), size: 18.w),
|
||||
SizedBox(width: 8.w),
|
||||
Expanded(child: warning.toText14(color: AppColors.textColorLight, height: 1.5, weight: FontWeight.w400)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Medicine Interactions Section
|
||||
if (analysis.medicineInteractions != null && analysis.medicineInteractions!.isNotEmpty) {
|
||||
expandableItems.add(
|
||||
ExpandableListItem(
|
||||
backgroundColor: Colors.transparent,
|
||||
expandedBackgroundColor: Colors.transparent,
|
||||
title: LocaleKeys.medicineInteractions.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor),
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 12.r,
|
||||
side: BorderSide(width: 1, color: Color(0xFFFFAF15)),
|
||||
),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: analysis.medicineInteractions!.map((interaction) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: 8.h),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(Icons.info_outline, color: Color(0xFFFFAF15), size: 18.w),
|
||||
SizedBox(width: 8.w),
|
||||
Expanded(child: interaction.toText14(color: AppColors.textColorLight, height: 1.5, weight: FontWeight.w400)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Follow-up Needed Section
|
||||
if (analysis.followUpNeeded != null && analysis.followUpNeeded!.isNotEmpty) {
|
||||
expandableItems.add(
|
||||
ExpandableListItem(
|
||||
backgroundColor: Colors.transparent,
|
||||
expandedBackgroundColor: Colors.transparent,
|
||||
title: LocaleKeys.followUpNeeded.tr(context: context).toText18(weight: FontWeight.w700, color: AppColors.blackColor),
|
||||
children: [
|
||||
SizedBox(height: 10.h),
|
||||
Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 12.r,
|
||||
side: BorderSide(width: 1, color: AppColors.primaryRedColor),
|
||||
),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: (analysis.followUpNeeded ?? "").toText14(color: AppColors.textColorLight, height: 1.5, weight: FontWeight.w400),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
if (expandableItems.isEmpty)
|
||||
Utils.getNoDataWidget(context)
|
||||
else
|
||||
CustomExpandableList(
|
||||
expansionMode: ExpansionMode.exactlyOne,
|
||||
dividerColor: AppColors.dividerColor,
|
||||
itemPadding: EdgeInsets.symmetric(vertical: 16.h, horizontal: 14.h),
|
||||
items: expandableItems,
|
||||
theme: ExpandableListTheme.custom(
|
||||
defaultTrailingIcon: Utils.buildSvgWithAssets(
|
||||
icon: AppAssets.arrow_down,
|
||||
height: 22.h,
|
||||
width: 22.w,
|
||||
iconColor: AppColors.textColor,
|
||||
),
|
||||
),
|
||||
).paddingSymmetrical(16.w, 0.0),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(Icons.info_outline, color: AppColors.greyTextColor, size: 20.r),
|
||||
SizedBox(width: 8.w),
|
||||
Expanded(
|
||||
child: ("${LocaleKeys.disclaimer.tr()}:${LocaleKeys.thisAboveInfo.tr()}").toText12(color: AppColors.greyTextColor, fontWeight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
).paddingSymmetrical(16.w, 16.h)
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMedicineCard(MedicineAnalysis medicine) {
|
||||
return Container(
|
||||
decoration: RoundedRectangleBorder().toSmoothCornerDecoration(
|
||||
color: AppColors.whiteColor,
|
||||
borderRadius: 12.r,
|
||||
side: BorderSide(width: 1, color: Color(0xFF4CAF50)),
|
||||
),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Medicine Name
|
||||
(medicine.medicineName ?? "").toText16(isBold: true, color: AppColors.blackColor),
|
||||
SizedBox(height: 12.h),
|
||||
|
||||
// Benefit
|
||||
if (medicine.benefit != null && medicine.benefit!.isNotEmpty) ...[
|
||||
_buildInfoRow(
|
||||
icon: Icons.medication_rounded,
|
||||
iconColor: Color(0xFF4CAF50),
|
||||
title: LocaleKeys.benefit.tr(context: context),
|
||||
content: medicine.benefit!,
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
],
|
||||
|
||||
// Common Side Effects
|
||||
if (medicine.commonSideEffects != null && medicine.commonSideEffects!.isNotEmpty) ...[
|
||||
_buildInfoRow(
|
||||
icon: Icons.warning_amber_rounded,
|
||||
iconColor: Color(0xFFFFAF15),
|
||||
title: LocaleKeys.commonSideEffects.tr(context: context),
|
||||
content: medicine.commonSideEffects!.join(', '),
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
],
|
||||
|
||||
// Serious Warnings
|
||||
if (medicine.seriousWarnings != null && medicine.seriousWarnings!.isNotEmpty) ...[
|
||||
_buildInfoRow(
|
||||
icon: Icons.error_outline,
|
||||
iconColor: Color(0xFFFF5252),
|
||||
title: LocaleKeys.seriousWarnings.tr(context: context),
|
||||
content: medicine.seriousWarnings!.join(', '),
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
],
|
||||
|
||||
// Storage
|
||||
if (medicine.storage != null && medicine.storage!.isNotEmpty) ...[
|
||||
_buildInfoRow(
|
||||
icon: Icons.inventory_2_outlined,
|
||||
iconColor: Color(0xFF2196F3),
|
||||
title: LocaleKeys.storage.tr(context: context),
|
||||
content: medicine.storage!,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildInfoRow({
|
||||
required IconData icon,
|
||||
required Color iconColor,
|
||||
required String title,
|
||||
required String content,
|
||||
}) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Row(
|
||||
// children: [
|
||||
// // Icon(icon, color: iconColor, size: 18.w),
|
||||
// SizedBox(width: 8.w),
|
||||
// // title.toText14(isBold: true, color: AppColors.blackColor),
|
||||
// ],
|
||||
// ),
|
||||
SizedBox(height: 4.h),
|
||||
content.toText14(color: AppColors.textColorLight, height: 1.5, weight: FontWeight.w400),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue