Change patient profile folder to patient manager

This commit is contained in:
2025-10-23 11:01:39 +02:00
parent 9bd039ca25
commit ac22e50eca
31 changed files with 29 additions and 29 deletions

View File

@@ -0,0 +1,79 @@
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/patient_add.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/patient_profile.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart';
class AddOrViewPatient extends StatefulWidget {
//final AppUser signedInUser;
final PatientViewArguments arguments;
const AddOrViewPatient({
super.key,
required this.arguments,
});
@override
State<AddOrViewPatient> createState() => _AddOrViewPatientState();
}
class _AddOrViewPatientState extends State<AddOrViewPatient> {
late double width;
late double height;
late Widget loading;
late Future<Patient?> patient;
Future<Patient?> fetchPatientData() async {
return await MihPatientServices()
.getPatientDetails(widget.arguments.signedInUser.app_id);
}
@override
void initState() {
super.initState();
patient = fetchPatientData();
}
@override
Widget build(BuildContext context) {
print("AddOrViewPatient");
var size = MediaQuery.of(context).size;
setState(() {
width = size.width;
height = size.height;
});
return FutureBuilder(
future: patient,
builder: (ctx, snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
// Extracting data from snapshot object
//final data = snapshot.data as String;
return PatientProfile(
arguments: PatientViewArguments(
widget.arguments.signedInUser,
snapshot.requireData,
null,
null,
widget.arguments.type,
));
} else if (snapshot.connectionState == ConnectionState.waiting) {
loading = Container(
width: width,
height: height,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
child: const Mihloadingcircle(),
);
return loading;
} else {
return AddPatient(signedInUser: widget.arguments.signedInUser);
}
},
);
}
}

View File

@@ -0,0 +1,536 @@
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_claim_statement_generation_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_icd10_code_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_date_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_radio_options.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/icd10_code.dart.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/components/icd10_search_window.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class ClaimStatementWindow extends StatefulWidget {
final Patient selectedPatient;
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final String env;
const ClaimStatementWindow({
super.key,
required this.selectedPatient,
required this.signedInUser,
required this.business,
required this.businessUser,
required this.env,
});
@override
State<ClaimStatementWindow> createState() => _ClaimStatementWindowState();
}
class _ClaimStatementWindowState extends State<ClaimStatementWindow> {
final TextEditingController _docTypeController = TextEditingController();
final TextEditingController _fullNameController = TextEditingController();
final TextEditingController _idController = TextEditingController();
final TextEditingController _medAidController = TextEditingController();
final TextEditingController _medAidNoController = TextEditingController();
final TextEditingController _medAidCodeController = TextEditingController();
final TextEditingController _medAidNameController = TextEditingController();
final TextEditingController _medAidSchemeController = TextEditingController();
final TextEditingController _providerNameController = TextEditingController();
final TextEditingController _practiceNoController = TextEditingController();
final TextEditingController _vatNoController = TextEditingController();
final TextEditingController _serviceDateController = TextEditingController();
final TextEditingController _serviceDescController = TextEditingController();
final TextEditingController _serviceDescOptionsController =
TextEditingController();
final TextEditingController _prcedureNameController = TextEditingController();
// final TextEditingController _procedureDateController =
// TextEditingController();
final TextEditingController _proceedureAdditionalInfoController =
TextEditingController();
final TextEditingController _icd10CodeController = TextEditingController();
final TextEditingController _amountController = TextEditingController();
final TextEditingController _preauthNoController = TextEditingController();
final ValueNotifier<String> serviceDesc = ValueNotifier("");
final ValueNotifier<String> medAid = ValueNotifier("");
List<ICD10Code> icd10codeList = [];
final FocusNode _searchFocusNode = FocusNode();
final _formKey = GlobalKey<FormState>();
void icd10SearchWindow(List<ICD10Code> codeList) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => ICD10SearchWindow(
icd10CodeController: _icd10CodeController,
icd10codeList: codeList,
),
);
}
Widget getWindowBody(double width) {
return Padding(
padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: width * 0.05)
: const EdgeInsets.symmetric(horizontal: 0),
child: Column(
children: [
MihForm(
formKey: _formKey,
formFields: [
MihRadioOptions(
controller: _docTypeController,
hintText: "Document Type",
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
secondaryFillColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
requiredText: true,
radioOptions: const ["Claim", "Statement"],
),
const SizedBox(height: 10),
Center(
child: Text(
"Service Details",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
),
Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
const SizedBox(height: 10),
MihDateField(
controller: _serviceDateController,
labelText: "Date of Service",
required: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10),
MihRadioOptions(
controller: _serviceDescController,
hintText: "Serviced Description",
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
secondaryFillColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
requiredText: true,
radioOptions: const [
"Consultation",
"Procedure",
"Other",
],
),
const SizedBox(height: 10),
ValueListenableBuilder(
valueListenable: serviceDesc,
builder: (BuildContext context, String value, Widget? child) {
Widget returnWidget;
switch (value) {
case 'Consultation':
returnWidget = Column(
key: const ValueKey('consultation_fields'), // Added key
children: [
MihRadioOptions(
key: const ValueKey('consultation_type_dropdown'),
controller: _serviceDescOptionsController,
hintText: "Consultation Type",
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
secondaryFillColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
requiredText: true,
radioOptions: const [
"General Consultation",
"Follow-Up Consultation",
"Specialist Consultation",
"Emergency Consultation",
],
),
const SizedBox(height: 10),
],
);
break;
case 'Procedure':
returnWidget = Column(
key: const ValueKey('procedure_fields'), // Added key
children: [
MihTextFormField(
key: const ValueKey(
'procedure_name_field'), // Added key
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: _prcedureNameController,
multiLineInput: false,
requiredText: true,
hintText: "Procedure Name",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10),
MihTextFormField(
key: const ValueKey(
'procedure_additional_info_field'), // Added key
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: _proceedureAdditionalInfoController,
multiLineInput: false,
requiredText: true,
hintText: "Additional Procedure Information",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 15),
],
);
break;
case 'Other':
returnWidget = Column(
key: const ValueKey('other_fields'), // Added key
children: [
MihTextFormField(
key: const ValueKey(
'other_service_description_field'), // Added key
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: _serviceDescOptionsController,
multiLineInput: false,
requiredText: true,
hintText: "Service Description Details",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10),
],
);
break;
default:
returnWidget = const SizedBox(
key: const ValueKey('empty_fields')); // Added key
}
return returnWidget;
},
),
Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text("ICD-10 Code & Description",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
)),
),
const SizedBox(height: 4),
MihSearchBar(
controller: _icd10CodeController,
hintText: "ICD-10 Search",
prefixIcon: Icons.search,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onPrefixIconTap: () {
MIHIcd10CodeApis.getIcd10Codes(
_icd10CodeController.text, context)
.then((result) {
icd10SearchWindow(result);
});
},
onClearIconTap: () {
_icd10CodeController.clear();
},
searchFocusNode: _searchFocusNode,
),
],
),
const SizedBox(height: 10),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: _amountController,
multiLineInput: false,
requiredText: true,
numberMode: true,
hintText: "Service Cost",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10),
Center(
child: Text(
"Additional Infomation",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
),
Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
const SizedBox(height: 10),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: _preauthNoController,
multiLineInput: false,
requiredText: false,
hintText: "Pre-authorisation No.",
),
const SizedBox(height: 20),
Center(
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
if (isInputValid()) {
MIHClaimStatementGenerationApi().generateClaimStatement(
ClaimStatementGenerationArguments(
_docTypeController.text,
widget.selectedPatient.app_id,
_fullNameController.text,
_idController.text,
_medAidController.text,
_medAidNoController.text,
_medAidCodeController.text,
_medAidNameController.text,
_medAidSchemeController.text,
widget.business!.Name,
"*To-Be Added*",
widget.business!.contact_no,
widget.business!.bus_email,
_providerNameController.text,
_practiceNoController.text,
_vatNoController.text,
_serviceDateController.text,
_serviceDescController.text,
_serviceDescOptionsController.text,
_prcedureNameController.text,
_proceedureAdditionalInfoController.text,
_icd10CodeController.text,
_amountController.text,
_preauthNoController.text,
widget.business!.logo_path,
widget.businessUser!.sig_path,
),
PatientViewArguments(
widget.signedInUser,
widget.selectedPatient,
widget.businessUser,
widget.business,
"business",
),
widget.env,
context);
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(
errorType: "Input Error");
},
);
}
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Generate",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
],
),
);
}
void serviceDescriptionSelected() {
String selectedType = _serviceDescController.text;
serviceDesc.value = selectedType;
if (selectedType == 'Consultation') {
_prcedureNameController.clear();
_proceedureAdditionalInfoController.clear();
} else if (selectedType == 'Procedure') {
_serviceDescOptionsController.clear();
} else if (selectedType == 'Other') {
_prcedureNameController.clear();
_proceedureAdditionalInfoController.clear();
} else {
_prcedureNameController.clear();
_proceedureAdditionalInfoController.clear();
_serviceDescOptionsController.clear();
}
}
void hasMedAid() {
if (_medAidController.text.isNotEmpty) {
} else {
medAid.value = "";
}
}
bool isInputValid() {
if (_docTypeController.text.isEmpty ||
_serviceDateController.text.isEmpty ||
_icd10CodeController.text.isEmpty ||
_amountController.text.isEmpty) {
return false;
}
switch (_serviceDescController.text) {
case 'Consultation':
case 'Other':
if (_serviceDescOptionsController.text.isEmpty) {
return false;
}
break;
case 'Procedure':
if (_prcedureNameController.text.isEmpty ||
_proceedureAdditionalInfoController.text.isEmpty) {
return false;
}
break;
default:
return false;
}
return true;
}
String getUserTitle() {
if (widget.businessUser!.title == "Doctor") {
return "Dr.";
} else {
return widget.businessUser!.title;
}
}
String getTodayDate() {
DateTime today = DateTime.now();
return DateFormat('yyyy-MM-dd').format(today);
}
@override
void dispose() {
_docTypeController.dispose();
_fullNameController.dispose();
_idController.dispose();
_medAidController.dispose();
_medAidNoController.dispose();
_medAidCodeController.dispose();
_medAidNameController.dispose();
_medAidSchemeController.dispose();
_providerNameController.dispose();
_practiceNoController.dispose();
_vatNoController.dispose();
_serviceDateController.dispose();
_serviceDescController.dispose();
_serviceDescOptionsController.dispose();
_prcedureNameController.dispose();
// _procedureDateController.dispose();
_proceedureAdditionalInfoController.dispose();
_icd10CodeController.dispose();
_preauthNoController.dispose();
_searchFocusNode.dispose();
serviceDesc.dispose();
medAid.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
_serviceDescController.text = "Consultation";
_serviceDescController.addListener(serviceDescriptionSelected);
serviceDesc.value = "Consultation";
_medAidController.addListener(hasMedAid);
_fullNameController.text =
"${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}";
_idController.text = widget.selectedPatient.id_no;
_medAidController.text = widget.selectedPatient.medical_aid;
_medAidNameController.text = widget.selectedPatient.medical_aid_name;
_medAidCodeController.text = widget.selectedPatient.medical_aid_code;
_medAidNoController.text = widget.selectedPatient.medical_aid_no;
_medAidSchemeController.text = widget.selectedPatient.medical_aid_scheme;
_serviceDateController.text = getTodayDate();
_providerNameController.text =
"${getUserTitle()} ${widget.signedInUser.fname} ${widget.signedInUser.lname}";
_practiceNoController.text = widget.business!.practice_no;
_vatNoController.text = widget.business!.vat_no;
hasMedAid();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageWindow(
fullscreen: false,
windowTitle: "Generate Claim/ Statement Document",
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: getWindowBody(screenWidth),
);
}
}

View File

@@ -0,0 +1,364 @@
import 'dart:async';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import '../../../../main.dart';
import 'package:syncfusion_flutter_core/theme.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
import "package:universal_html/html.dart" as html;
import 'package:http/http.dart' as http;
import 'package:printing/printing.dart';
import 'package:fl_downloader/fl_downloader.dart';
import '../../../../mih_components/mih_layout/mih_action.dart';
import '../../../../mih_components/mih_layout/mih_body.dart';
import '../../../../mih_components/mih_layout/mih_header.dart';
import '../../../../mih_components/mih_layout/mih_layout_builder.dart';
class FullScreenFileViewer extends StatefulWidget {
final FileViewArguments arguments;
const FullScreenFileViewer({
super.key,
required this.arguments,
});
@override
State<FullScreenFileViewer> createState() => _FullScreenFileViewerState();
}
class _FullScreenFileViewerState extends State<FullScreenFileViewer> {
late PdfViewerController pdfViewerController = PdfViewerController();
int currentPageCount = 0;
int currentPage = 0;
double startZoomLevel = 1.0;
double zoomOut = 0;
int progress = 0;
late StreamSubscription progressStream;
String getExtType(String path) {
//print(pdfLink.split(".")[1]);
return path.split(".").last;
}
String getFileName(String path) {
//print(pdfLink.split(".")[1]);
return path.split("/").last;
}
void onPageSelect() {
setState(() {
currentPage = pdfViewerController.pageNumber;
});
}
void printDocument() async {
print("Printing ${widget.arguments.path.split("/").last}");
http.Response response = await http.get(Uri.parse(widget.arguments.link));
var pdfData = response.bodyBytes;
Navigator.of(context).pushNamed(
'/file-veiwer/print-preview',
arguments: pdfData,
);
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) => PdfPreview(
// initialPageFormat: PdfPageFormat.a4,
// build: (format) => pdfData,
// ),
// ),
// );
// try {
// await Printing.layoutPdf(
// onLayout: (PdfPageFormat format) async => pdfData);
// } on Exception catch (_) {
// print("Print Error");
// }
}
void shareDocument() async {
http.Response response = await http.get(Uri.parse(widget.arguments.link));
var pdfData = response.bodyBytes;
await Printing.sharePdf(
bytes: pdfData, filename: widget.arguments.path.split("/").last);
}
MIHAction getActionButton() {
return MIHAction(
icon: const Icon(
Icons.fullscreen_exit,
),
iconSize: 35,
onTap: () {
Navigator.pop(context);
},
);
}
MIHHeader getHeader(double width) {
bool isPDF;
if (getExtType(widget.arguments.path).toLowerCase() == "pdf") {
isPDF = true;
} else {
isPDF = false;
}
return MIHHeader(
headerAlignment: MainAxisAlignment.end,
headerItems: [
Visibility(
visible: isPDF,
child: IconButton(
iconSize: 30,
padding: const EdgeInsets.all(0),
onPressed: () {
pdfViewerController.previousPage();
//print(pdfViewerController.);
//if (pdfViewerController.pageNumber > 1) {
setState(() {
currentPage = pdfViewerController.pageNumber;
});
// }
},
icon: Icon(
Icons.arrow_back,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
),
Visibility(
visible: isPDF,
child: Text(
"$currentPage / $currentPageCount",
style: const TextStyle(fontSize: 20),
),
),
Visibility(
visible: isPDF,
child: IconButton(
iconSize: 30,
padding: const EdgeInsets.all(0),
onPressed: () {
pdfViewerController.nextPage();
//print(pdfViewerController.pageNumber);
//if (pdfViewerController.pageNumber < currentPageCount) {
setState(() {
currentPage = pdfViewerController.pageNumber;
});
//}
},
icon: Icon(
Icons.arrow_forward,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
),
Visibility(
visible: isPDF,
child: IconButton(
iconSize: 30,
padding: const EdgeInsets.all(0),
onPressed: () {
if (zoomOut > 0) {
setState(() {
zoomOut = zoomOut - 100;
});
} else {
setState(() {
pdfViewerController.zoomLevel = startZoomLevel + 0.25;
startZoomLevel = pdfViewerController.zoomLevel;
});
}
},
icon: Icon(
Icons.zoom_in,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
),
Visibility(
visible: isPDF,
child: IconButton(
iconSize: 30,
padding: const EdgeInsets.all(0),
onPressed: () {
if (pdfViewerController.zoomLevel > 1) {
setState(() {
pdfViewerController.zoomLevel = startZoomLevel - 0.25;
startZoomLevel = pdfViewerController.zoomLevel;
});
} else {
if (zoomOut < (width - 100)) {
setState(() {
zoomOut = zoomOut + 100;
});
}
}
},
icon: Icon(
Icons.zoom_out,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
),
// IconButton(
// iconSize: 30,
// padding: const EdgeInsets.all(0),
// onPressed: () {
// printDocument();
// },
// icon: Icon(
// Icons.print,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
IconButton(
iconSize: 30,
padding: const EdgeInsets.all(0),
onPressed: () {
if (MzansiInnovationHub.of(context)!.theme.getPlatform() == "Web") {
html.window.open(
widget.arguments.link,
// '${AppEnviroment.baseFileUrl}/mih/$filePath',
'download');
} else {
nativeFileDownload(
widget.arguments.link,
);
}
},
icon: Icon(
Icons.download,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
],
);
}
MIHBody getBody(double width, double height) {
Widget fileViewer;
if (getExtType(widget.arguments.path).toLowerCase() == "pdf") {
fileViewer = SizedBox(
width: width - zoomOut,
height: height - 70,
child: SfPdfViewerTheme(
data: SfPdfViewerThemeData(
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
child: SfPdfViewer.network(
widget.arguments.link,
controller: pdfViewerController,
initialZoomLevel: startZoomLevel,
pageSpacing: 2,
maxZoomLevel: 5,
interactionMode: PdfInteractionMode.pan,
onDocumentLoaded: (details) {
setState(() {
currentPage = pdfViewerController.pageNumber;
currentPageCount = pdfViewerController.pageCount;
});
},
),
),
);
} else {
fileViewer = SizedBox(
width: width,
height: height - 70,
child: InteractiveViewer(
maxScale: 5.0,
//minScale: 0.,
child: Image.network(widget.arguments.link),
),
);
}
return MIHBody(
borderOn: false,
bodyItems: [
fileViewer,
],
);
}
void mihLoadingPopUp() {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
}
void nativeFileDownload(String fileLink) async {
var permission = await FlDownloader.requestPermission();
if (permission == StoragePermissionStatus.granted) {
try {
mihLoadingPopUp();
await FlDownloader.download(fileLink);
Navigator.of(context).pop();
} on Exception catch (error) {
Navigator.of(context).pop();
print(error);
}
} else {
print("denied");
}
}
@override
void dispose() {
pdfViewerController.dispose();
progressStream.cancel();
super.dispose();
}
@override
void initState() {
//pdfViewerController = widget.arguments.pdfViewerController!;
pdfViewerController.addListener(onPageSelect);
FlDownloader.initialize();
progressStream = FlDownloader.progressStream.listen((event) {
if (event.status == DownloadStatus.successful) {
setState(() {
progress = event.progress;
});
//Navigator.of(context).pop();
print("Progress $progress%: Success Downloading");
FlDownloader.openFile(filePath: event.filePath);
} else if (event.status == DownloadStatus.failed) {
print("Progress $progress%: Error Downloading");
} else if (event.status == DownloadStatus.running) {
print("Progress $progress%: Download Running");
}
});
super.initState();
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.sizeOf(context);
double width = size.width;
double height = size.height;
return MIHLayoutBuilder(
actionButton: getActionButton(),
header: getHeader(width),
secondaryActionButton: null,
body: getBody(width, height),
actionDrawer: null,
secondaryActionDrawer: null,
bottomNavBar: null,
pullDownToRefresh: false,
onPullDown: () async {},
);
}
}

View File

@@ -0,0 +1,79 @@
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/icd10_code.dart.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_icd10_code_list.dart';
import 'package:flutter/material.dart';
class ICD10SearchWindow extends StatefulWidget {
final TextEditingController icd10CodeController;
final List<ICD10Code> icd10codeList;
const ICD10SearchWindow({
super.key,
required this.icd10CodeController,
required this.icd10codeList,
});
@override
State<ICD10SearchWindow> createState() => _ICD10SearchWindowState();
}
class _ICD10SearchWindowState extends State<ICD10SearchWindow> {
Widget getWindowBody() {
return Column(
children: [
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: widget.icd10CodeController,
multiLineInput: false,
requiredText: true,
numberMode: true,
hintText: "ICD-10 Code Searched",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 15),
Text(
"Search for ICD-10 Codes",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
BuildICD10CodeList(
icd10CodeController: widget.icd10CodeController,
icd10codeList: widget.icd10codeList,
),
],
);
}
@override
Widget build(BuildContext context) {
return MihPackageWindow(
fullscreen: false,
windowTitle: "ICD-10 Search",
onWindowTapClose: () {
// medicineController.clear();
// quantityController.clear();
// dosageController.clear();
// timesDailyController.clear();
// noDaysController.clear();
// noRepeatsController.clear();
Navigator.pop(context);
},
windowBody: getWindowBody(),
);
}
}

View File

@@ -0,0 +1,112 @@
import 'dart:convert';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/medicine.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_med_list.dart';
import 'package:flutter/material.dart';
import 'package:supertokens_flutter/http.dart' as http;
class MedicineSearch extends StatefulWidget {
final TextEditingController searchVlaue;
const MedicineSearch({
super.key,
required this.searchVlaue,
});
@override
State<MedicineSearch> createState() => _MedicineSearchState();
}
class _MedicineSearchState extends State<MedicineSearch> {
final String endpointMeds = "${AppEnviroment.baseApiUrl}/users/medicine/";
//TextEditingController searchController = TextEditingController();
late Future<List<Medicine>> futueMeds;
//String searchString = "";
Future<List<Medicine>> getMedList(String endpoint) async {
final response = await http.get(Uri.parse(endpoint));
if (response.statusCode == 200) {
Iterable l = jsonDecode(response.body);
List<Medicine> medicines =
List<Medicine>.from(l.map((model) => Medicine.fromJson(model)));
// List<Medicine> meds = [];
// medicines.forEach((element) => meds.add(element.name));
return medicines;
} else {
internetConnectionPopUp();
throw Exception('failed to load medicine');
}
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
@override
void dispose() {
super.dispose();
}
@override
void initState() {
futueMeds = getMedList(endpointMeds + widget.searchVlaue.text);
super.initState();
}
@override
Widget build(BuildContext context) {
return MihPackageWindow(
fullscreen: false,
windowTitle: "Select Medicine",
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: Column(
children: [
FutureBuilder(
future: futueMeds,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const SizedBox(
height: 400,
child: Mihloadingcircle(),
);
} else if (snapshot.hasData && snapshot.data!.isNotEmpty) {
final medsList = snapshot.data!;
return SizedBox(
height: 400,
child: BuildMedicinesList(
contoller: widget.searchVlaue,
medicines: medsList,
//searchString: searchString,
),
);
} else {
return const SizedBox(
height: 400,
child: Center(
child: Text(
"No Match Found\nPlease close and manually capture medicine",
style: TextStyle(fontSize: 25, color: Colors.grey),
textAlign: TextAlign.center,
),
),
);
}
},
),
],
),
);
}
}

View File

@@ -0,0 +1,610 @@
import 'dart:convert';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_numeric_stepper.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/components/medicine_search.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_success_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/perscription.dart';
import 'package:flutter/material.dart';
import 'package:supertokens_flutter/http.dart' as http;
class PrescripInput extends StatefulWidget {
final TextEditingController medicineController;
final TextEditingController quantityController;
final TextEditingController dosageController;
final TextEditingController timesDailyController;
final TextEditingController noDaysController;
final TextEditingController noRepeatsController;
final TextEditingController outputController;
final Patient selectedPatient;
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final String env;
const PrescripInput({
super.key,
required this.medicineController,
required this.quantityController,
required this.dosageController,
required this.timesDailyController,
required this.noDaysController,
required this.noRepeatsController,
required this.outputController,
required this.selectedPatient,
required this.signedInUser,
required this.business,
required this.businessUser,
required this.env,
});
@override
State<PrescripInput> createState() => _PrescripInputState();
}
class _PrescripInputState extends State<PrescripInput> {
final FocusNode _focusNode = FocusNode();
final FocusNode _searchFocusNode = FocusNode();
final _formKey = GlobalKey<FormState>();
List<Perscription> perscriptionObjOutput = [];
late double width;
late double height;
final numberOptions = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
"13",
"14",
"15",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"23",
"24",
"25",
"26",
"27",
"28",
"29",
"30"
];
Future<void> generatePerscription() async {
//start loading circle
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
DateTime now = new DateTime.now();
// DateTime date = new DateTime(now.year, now.month, now.day);
String fileName =
"Perscription-${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}-${now.toString().substring(0, 19)}.pdf"
.replaceAll(RegExp(r' '), '-');
var response1 = await http.post(
Uri.parse("${AppEnviroment.baseApiUrl}/minio/generate/perscription/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"app_id": widget.selectedPatient.app_id,
"env": widget.env,
"patient_full_name":
"${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}",
"fileName": fileName,
"id_no": widget.selectedPatient.id_no,
"docfname":
"DR. ${widget.signedInUser.fname} ${widget.signedInUser.lname}",
"busName": widget.business!.Name,
"busAddr": "*TO BE ADDED IN THE FUTURE*",
"busNo": widget.business!.contact_no,
"busEmail": widget.business!.bus_email,
"logo_path": widget.business!.logo_path,
"sig_path": widget.businessUser!.sig_path,
"data": perscriptionObjOutput,
}),
);
//print(response1.statusCode);
if (response1.statusCode == 200) {
var response2 = await http.post(
Uri.parse("${AppEnviroment.baseApiUrl}/patient_files/insert/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"file_path":
"${widget.selectedPatient.app_id}/patient_files/$fileName",
"file_name": fileName,
"app_id": widget.selectedPatient.app_id
}),
);
//print(response2.statusCode);
if (response2.statusCode == 201) {
setState(() {
//To do
widget.medicineController.clear();
widget.dosageController.clear();
widget.timesDailyController.clear();
widget.noDaysController.clear();
widget.timesDailyController.clear();
widget.noRepeatsController.clear();
widget.quantityController.clear();
widget.outputController.clear();
// futueFiles = fetchFiles();
});
// end loading circle
Navigator.of(context).pop();
Navigator.of(context).pop();
Navigator.of(context).pop();
Navigator.of(context).pushNamed('/patient-manager/patient',
arguments: PatientViewArguments(
widget.signedInUser,
widget.selectedPatient,
widget.businessUser,
widget.business,
"business",
));
String message =
"The perscription $fileName has been successfully generated and added to ${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}'s record. You can now access and download it for their use.";
successPopUp(message);
} else {
internetConnectionPopUp();
}
} else {
internetConnectionPopUp();
}
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
void successPopUp(String message) {
showDialog(
context: context,
builder: (context) {
return MIHSuccessMessage(
successType: "Success",
successMessage: message,
);
},
);
}
void getMedsPopUp(TextEditingController medSearch) {
showDialog(
context: context,
builder: (context) {
return MedicineSearch(
searchVlaue: medSearch,
);
},
);
}
bool isFieldsFilled() {
if (widget.medicineController.text.isEmpty) {
return false;
} else {
return true;
}
}
void updatePerscriptionList() {
String name;
String unit;
String form;
List<String> medNameList = widget.medicineController.text.split("%t");
if (medNameList.length == 1) {
name = medNameList[0];
unit = "";
form = "";
} else {
name = medNameList[0];
unit = medNameList[1];
form = medNameList[2];
}
int quantityCalc = calcQuantity(
widget.dosageController.text,
widget.timesDailyController.text,
widget.noDaysController.text,
medNameList[2].toLowerCase());
Perscription tempObj = Perscription(
name: name,
unit: unit,
form: form,
fullForm: getFullDoagesForm(form),
quantity: "$quantityCalc",
dosage: widget.dosageController.text,
times: widget.timesDailyController.text,
days: widget.noDaysController.text,
repeats: widget.noRepeatsController.text,
);
perscriptionObjOutput.add(tempObj);
}
String getPerscTitle(int index) {
return "${perscriptionObjOutput[index].name} - ${perscriptionObjOutput[index].form}";
}
String getPerscSubtitle(int index) {
if (perscriptionObjOutput[index].form.toLowerCase() == "syr") {
String unit = perscriptionObjOutput[index].unit.toLowerCase();
if (perscriptionObjOutput[index].unit.toLowerCase().contains("ml")) {
unit = "ml";
}
return "${perscriptionObjOutput[index].dosage} $unit, ${perscriptionObjOutput[index].times} time(s) daily, for ${perscriptionObjOutput[index].days} day(s)\nQuantity: ${perscriptionObjOutput[index].quantity}\nNo. of repeats: ${perscriptionObjOutput[index].repeats}";
} else {
return "${perscriptionObjOutput[index].dosage} ${perscriptionObjOutput[index].fullForm}(s), ${perscriptionObjOutput[index].times} time(s) daily, for ${perscriptionObjOutput[index].days} day(s)\nQuantity: ${perscriptionObjOutput[index].quantity}\nNo. of repeats: ${perscriptionObjOutput[index].repeats}";
}
}
String getFullDoagesForm(String abr) {
var dosageFormList = {
"liq": "liquid",
"tab": "tablet",
"cap": "capsule",
"cps": "capsule",
"oin": "ointment",
"lit": "lotion",
"lot": "lotion",
"inj": "injection",
"syr": "syrup",
"dsp": "effervescent tablet",
"eft": "effervescent tablet",
"ear": "drops",
"drp": "drops",
"opd": "drops",
"udv": "vial",
"sus": "suspension",
"susp": "suspension",
"cal": "calasthetic",
"sol": "solution",
"sln": "solution",
"neb": "nebuliser",
"inh": "inhaler",
"spo": "inhaler",
"inf": "infusion",
"chg": "chewing Gum",
"vac": "vacutainer",
"vag": "vaginal gel",
"jel": "gel",
"eyo": "eye ointment",
"vat": "vaginal cream",
"poi": "injection",
"ped": "powder",
"pow": "powder",
"por": "powder",
"sac": "sachet",
"sup": "suppository",
"cre": "cream",
"ptd": "patch",
"ect": "tablet",
"nas": "spray",
};
String form;
if (dosageFormList[abr.toLowerCase()] == null) {
form = abr;
} else {
form = dosageFormList[abr.toLowerCase()]!;
}
return form;
}
int calcQuantity(String dosage, String times, String days, String form) {
var dosageFormList = [
"tab",
"cap",
"cps",
"dsp",
"eft",
"udv",
"chg",
"sac",
"sup",
"ptd",
"ect",
];
if (dosageFormList.contains(form)) {
return int.parse(dosage) * int.parse(times) * int.parse(days);
} else {
return 1;
}
}
Widget displayMedInput() {
return Column(
children: [
MihForm(
formKey: _formKey,
formFields: [
Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
"Medication",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
const SizedBox(height: 4),
MihSearchBar(
controller: widget.medicineController,
hintText: "Search Medicine",
prefixIcon: Icons.search,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onPrefixIconTap: () {
getMedsPopUp(widget.medicineController);
},
onClearIconTap: () {
widget.medicineController.clear();
},
searchFocusNode: _searchFocusNode,
),
],
),
const SizedBox(height: 10.0),
MihNumericStepper(
controller: widget.dosageController,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintText: "Dosage",
requiredText: true,
minValue: 1,
// maxValue: 5,
validationOn: true,
),
const SizedBox(height: 10.0),
MihNumericStepper(
controller: widget.timesDailyController,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintText: "Times Daily",
requiredText: true,
minValue: 1,
// maxValue: 5,
validationOn: true,
),
const SizedBox(height: 10.0),
MihNumericStepper(
controller: widget.noDaysController,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintText: "No. Days",
requiredText: true,
minValue: 1,
// maxValue: 5,
validationOn: true,
),
const SizedBox(height: 10.0),
MihNumericStepper(
controller: widget.noRepeatsController,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintText: "No.Repeats",
requiredText: true,
minValue: 0,
// maxValue: 5,
validationOn: true,
),
const SizedBox(height: 15.0),
Center(
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
if (isFieldsFilled()) {
setState(() {
updatePerscriptionList();
widget.medicineController.clear();
widget.quantityController.text = "1";
widget.dosageController.text = "1";
widget.timesDailyController.text = "1";
widget.noDaysController.text = "1";
widget.noRepeatsController.text = "0";
});
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(
errorType: "Input Error");
},
);
}
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Add",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
],
)
],
);
}
Widget displayPerscList() {
return Column(
children: [
Container(
width: 550,
height: 325,
decoration: BoxDecoration(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25.0),
border: Border.all(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 3.0),
),
child: ListView.separated(
separatorBuilder: (BuildContext context, int index) {
return const Padding(
padding: EdgeInsets.symmetric(horizontal: 10.0),
child: Divider(),
);
},
itemCount: perscriptionObjOutput.length,
itemBuilder: (context, index) {
//final patient = widget.patients[index].id_no.contains(widget.searchString);
return ListTile(
title: Text(
getPerscTitle(index),
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
subtitle: Text(
getPerscSubtitle(index),
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
//onTap: () {},
trailing: IconButton(
icon: Icon(
Icons.delete_forever_outlined,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
onPressed: () {
setState(() {
perscriptionObjOutput.removeAt(index);
});
},
),
);
},
),
),
const SizedBox(height: 15.0),
MihButton(
onPressed: () async {
if (perscriptionObjOutput.isNotEmpty) {
//print(jsonEncode(perscriptionObjOutput));
await generatePerscription();
Navigator.pop(context);
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Input Error");
},
);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Generate",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
);
}
@override
void dispose() {
_focusNode.dispose();
_searchFocusNode.dispose();
super.dispose();
}
@override
void initState() {
//futueMeds = getMedList(endpointMeds);
super.initState();
}
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
width = size.width;
height = size.height;
return Wrap(
direction: Axis.horizontal,
alignment: WrapAlignment.center,
spacing: 10,
runSpacing: 10,
// mainAxisAlignment: MainAxisAlignment.center,
// mainAxisSize: MainAxisSize.max,
// crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(width: 500, child: displayMedInput()),
displayPerscList(),
],
);
}
}

View File

@@ -0,0 +1,466 @@
import 'dart:async';
import 'package:fl_downloader/fl_downloader.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_claim_statement_generation_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_success_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/claim_statement_file.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_file_view.dart';
import 'package:flutter/material.dart';
import 'package:supertokens_flutter/http.dart' as http;
import 'package:http/http.dart' as http2;
import "package:universal_html/html.dart" as html;
class BuildClaimStatementFileList extends StatefulWidget {
final AppUser signedInUser;
final List<ClaimStatementFile> files;
final Patient selectedPatient;
final Business? business;
final BusinessUser? businessUser;
final String type;
final String env;
const BuildClaimStatementFileList({
super.key,
required this.files,
required this.signedInUser,
required this.selectedPatient,
required this.business,
required this.businessUser,
required this.type,
required this.env,
});
@override
State<BuildClaimStatementFileList> createState() =>
_BuildClaimStatementFileListState();
}
class _BuildClaimStatementFileListState
extends State<BuildClaimStatementFileList> {
int indexOn = 0;
final baseAPI = AppEnviroment.baseApiUrl;
final basefile = AppEnviroment.baseFileUrl;
String fileUrl = "";
int progress = 0;
late StreamSubscription progressStream;
Future<String> getFileUrlApiCall(String filePath) async {
String teporaryFileUrl = "";
await MihFileApi.getMinioFileUrl(
filePath,
context,
).then((value) {
teporaryFileUrl = value;
});
return teporaryFileUrl;
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
void successPopUp(String message) {
showDialog(
context: context,
builder: (context) {
return MIHSuccessMessage(
successType: "Success",
successMessage: message,
);
},
);
}
void deleteFilePopUp(String filePath, int fileID) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MIHDeleteMessage(
deleteType: "File",
onTap: () async {
//API Call here
await MIHClaimStatementGenerationApi
.deleteClaimStatementFilesByFileID(
PatientViewArguments(
widget.signedInUser,
widget.selectedPatient,
widget.businessUser,
widget.business,
"business",
),
widget.env,
filePath,
fileID,
context,
);
},
),
);
}
String getFileName(String path) {
//print(pdfLink.split(".")[1]);
return path.split("/").last;
}
void printDocument(String link, String path) async {
http2.Response response = await http.get(Uri.parse(link));
var pdfData = response.bodyBytes;
context.pop();
context.pushNamed(
'printPreview',
extra: PrintPreviewArguments(
pdfData,
getFileName(path),
),
);
// Navigator.of(context).pushNamed(
// '/file-veiwer/print-preview',
// arguments: PrintPreviewArguments(
// pdfData,
// getFileName(path),
// ),
// );
}
void nativeFileDownload(String fileLink) async {
var permission = await FlDownloader.requestPermission();
if (permission == StoragePermissionStatus.granted) {
try {
mihLoadingPopUp();
await FlDownloader.download(fileLink);
Navigator.of(context).pop();
} on Exception catch (error) {
Navigator.of(context).pop();
print(error);
}
} else {
print("denied");
}
}
void viewFilePopUp(String fileName, String filePath, int fileID, String url) {
bool hasAccessToDelete = false;
if (widget.type == "business") {
hasAccessToDelete = true;
}
List<SpeedDialChild>? menuList = [
SpeedDialChild(
child: Icon(
Icons.download,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Download",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
if (MzansiInnovationHub.of(context)!.theme.getPlatform() == "Web") {
html.window.open(url, 'download');
} else {
nativeFileDownload(url);
}
},
),
];
menuList.add(
SpeedDialChild(
child: Icon(
Icons.print,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Print",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
printDocument(url, filePath);
},
),
);
menuList.add(
SpeedDialChild(
child: Icon(
Icons.fullscreen,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Full Screen",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
context.pop();
context.pushNamed(
'fileViewer',
extra: FileViewArguments(
url,
filePath,
),
);
// printDocument(url, filePath);
},
),
);
if (hasAccessToDelete) {
menuList.add(
SpeedDialChild(
child: Icon(
Icons.delete,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Delete Document",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
deleteFilePopUp(filePath, fileID);
},
),
);
}
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: fileName,
windowBody: Column(
children: [
BuildFileView(
link: url,
path: filePath,
//pdfLink: '${AppEnviroment.baseFileUrl}/mih/$filePath',
),
const SizedBox(
height: 10,
)
],
),
menuOptions: menuList,
onWindowTapClose: () {
Navigator.pop(context);
},
),
);
}
void mihLoadingPopUp() {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
void initState() {
super.initState();
FlDownloader.initialize();
progressStream = FlDownloader.progressStream.listen((event) {
if (event.status == DownloadStatus.successful) {
setState(() {
progress = event.progress;
});
//Navigator.of(context).pop();
print("Progress $progress%: Success Downloading");
FlDownloader.openFile(filePath: event.filePath);
} else if (event.status == DownloadStatus.failed) {
print("Progress $progress%: Error Downloading");
} else if (event.status == DownloadStatus.running) {
print("Progress $progress%: Download Running");
}
});
}
@override
Widget build(BuildContext context) {
if (widget.files.isNotEmpty) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, int index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemCount: widget.files.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
widget.files[index].file_name,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
subtitle: Text(
widget.files[index].insert_date,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
// trailing: Icon(
// Icons.arrow_forward,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
onTap: () async {
await getFileUrlApiCall(widget.files[index].file_path)
.then((urlHere) {
//print(url);
setState(() {
fileUrl = urlHere;
});
});
viewFilePopUp(
widget.files[index].file_name,
widget.files[index].file_path,
widget.files[index].idclaim_statement_file,
fileUrl);
},
);
},
);
} else {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
const SizedBox(height: 50),
Stack(
alignment: AlignmentDirectional.center,
children: [
Icon(
MihIcons.mihRing,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
Icon(
Icons.file_open_outlined,
size: 110,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
],
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Text(
"No Claims or Statements have been added to this profile.",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
],
),
const SizedBox(height: 25),
Visibility(
visible: widget.business != null,
child: Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
children: [
TextSpan(text: "Press "),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Icon(
Icons.menu,
size: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
TextSpan(text: " to generate the first document"),
],
),
),
),
),
],
),
);
}
}
}

View File

@@ -0,0 +1,144 @@
import 'dart:async';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:syncfusion_flutter_core/theme.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
import 'package:http/http.dart' as http;
import 'package:fl_downloader/fl_downloader.dart';
class BuildFileView extends StatefulWidget {
final String link;
final String path;
const BuildFileView({
super.key,
required this.link,
required this.path,
});
@override
State<BuildFileView> createState() => _BuildFileViewState();
}
class _BuildFileViewState extends State<BuildFileView> {
late PdfViewerController pdfViewerController = PdfViewerController();
//late TextEditingController currentPageController = TextEditingController();
double startZoomLevel = 1;
int progress = 0;
late StreamSubscription progressStream;
void mihLoadingPopUp() {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
}
String getExtType(String path) {
//print(pdfLink.split(".")[1]);
return path.split(".").last;
}
String getFileName(String path) {
//print(pdfLink.split(".")[1]);
return path.split("/").last;
}
void printDocument() async {
print("Printing ${widget.path.split("/").last}");
http.Response response = await http.get(Uri.parse(widget.link));
var pdfData = response.bodyBytes;
Navigator.of(context).pushNamed(
'/file-veiwer/print-preview',
arguments: PrintPreviewArguments(
pdfData,
getFileName(
widget.path,
),
),
);
}
void nativeFileDownload(String fileLink) async {
var permission = await FlDownloader.requestPermission();
if (permission == StoragePermissionStatus.granted) {
try {
mihLoadingPopUp();
await FlDownloader.download(fileLink);
Navigator.of(context).pop();
} on Exception catch (error) {
Navigator.of(context).pop();
print(error);
}
} else {
print("denied");
}
}
@override
void dispose() {
pdfViewerController.dispose();
progressStream.cancel();
super.dispose();
}
@override
void initState() {
super.initState();
FlDownloader.initialize();
progressStream = FlDownloader.progressStream.listen((event) {
if (event.status == DownloadStatus.successful) {
setState(() {
progress = event.progress;
});
//Navigator.of(context).pop();
print("Progress $progress%: Success Downloading");
FlDownloader.openFile(filePath: event.filePath);
} else if (event.status == DownloadStatus.failed) {
print("Progress $progress%: Error Downloading");
} else if (event.status == DownloadStatus.running) {
print("Progress $progress%: Download Running");
}
});
}
@override
Widget build(BuildContext context) {
// double width = MediaQuery.sizeOf(context).width;
//double height = MediaQuery.sizeOf(context).height;
debugPrint(widget.link);
if (getExtType(widget.path).toLowerCase() == "pdf") {
return SizedBox(
height: 500,
child: SfPdfViewerTheme(
data: SfPdfViewerThemeData(
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
child: SfPdfViewer.network(
widget.link,
controller: pdfViewerController,
interactionMode: PdfInteractionMode.pan,
),
),
);
} else {
return SizedBox(
height: 500,
child: InteractiveViewer(
//constrained: true,
//clipBehavior: Clip.antiAlias,
maxScale: 5.0,
//minScale: 0.,
child: Image.network(widget.link),
),
);
}
}
}

View File

@@ -0,0 +1,500 @@
import 'dart:async';
import 'dart:convert';
import 'package:fl_downloader/fl_downloader.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_success_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/files.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_file_view.dart';
import 'package:flutter/material.dart';
import 'package:supertokens_flutter/http.dart' as http;
import 'package:http/http.dart' as http2;
import "package:universal_html/html.dart" as html;
class BuildFilesList extends StatefulWidget {
final AppUser signedInUser;
final List<PFile> files;
final Patient selectedPatient;
final Business? business;
final BusinessUser? businessUser;
final String type;
final String env;
const BuildFilesList({
super.key,
required this.files,
required this.signedInUser,
required this.selectedPatient,
required this.business,
required this.businessUser,
required this.type,
required this.env,
});
@override
State<BuildFilesList> createState() => _BuildFilesListState();
}
class _BuildFilesListState extends State<BuildFilesList> {
int indexOn = 0;
final baseAPI = AppEnviroment.baseApiUrl;
final basefile = AppEnviroment.baseFileUrl;
String fileUrl = "";
int progress = 0;
late StreamSubscription progressStream;
Future<String> getFileUrlApiCall(String filePath) async {
String teporaryFileUrl = "";
await MihFileApi.getMinioFileUrl(
filePath,
context,
).then((value) {
teporaryFileUrl = value;
});
return teporaryFileUrl;
}
Future<void> deleteFileApiCall(String filePath, int fileID) async {
var response = await MihFileApi.deleteFile(
widget.selectedPatient.app_id,
widget.env,
"patient_files",
filePath.split("/").last,
context,
);
if (response == 200) {
// delete file from database
await deletePatientFileLocationToDB(fileID);
} else {
String message =
"The File has not been deleted successfully. Please try again.";
successPopUp(message);
}
}
Future<void> deletePatientFileLocationToDB(int fileID) async {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
var response2 = await http.delete(
Uri.parse("$baseAPI/patient_files/delete/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"idpatient_files": fileID,
"env": widget.env,
}),
);
if (response2.statusCode == 200) {
context.pop(); //Remove Loading Dialog
context.pop(); //Remove Delete Dialog
context.pop(); //Remove File View Dialog
context.pop(); //Remove File List Dialog
//print(widget.business);
if (widget.business == null) {
context.pushNamed('patientManagerPatient',
extra: PatientViewArguments(
widget.signedInUser,
widget.selectedPatient,
widget.businessUser,
widget.business,
"personal"));
} else {
context.pushNamed('patientManagerPatient',
extra: PatientViewArguments(
widget.signedInUser,
widget.selectedPatient,
widget.businessUser,
widget.business,
"business"));
}
String message =
"The File has been deleted successfully. This means it will no longer be visible on your and cannot be used for future appointments.";
successPopUp(message);
} else {
internetConnectionPopUp();
}
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
void successPopUp(String message) {
showDialog(
context: context,
builder: (context) {
return MIHSuccessMessage(
successType: "Success",
successMessage: message,
);
},
);
}
void deleteFilePopUp(String filePath, int fileID) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MIHDeleteMessage(
deleteType: "File",
onTap: () async {
await deleteFileApiCall(filePath, fileID);
},
),
);
}
String getFileName(String path) {
//print(pdfLink.split(".")[1]);
return path.split("/").last;
}
void printDocument(String link, String path) async {
http2.Response response = await http.get(Uri.parse(link));
var pdfData = response.bodyBytes;
context.pop();
context.pushNamed(
'printPreview',
extra: PrintPreviewArguments(
pdfData,
getFileName(path),
),
);
}
void nativeFileDownload(String fileLink) async {
var permission = await FlDownloader.requestPermission();
if (permission == StoragePermissionStatus.granted) {
try {
mihLoadingPopUp();
await FlDownloader.download(fileLink);
Navigator.of(context).pop();
} on Exception catch (error) {
Navigator.of(context).pop();
print(error);
}
} else {
print("denied");
}
}
void viewFilePopUp(String fileName, String filePath, int fileID, String url) {
bool hasAccessToDelete = false;
if (widget.type == "business") {
hasAccessToDelete = true;
}
List<SpeedDialChild>? menuList = [
SpeedDialChild(
child: Icon(
Icons.download,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Download",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
if (MzansiInnovationHub.of(context)!.theme.getPlatform() == "Web") {
html.window.open(url, 'download');
} else {
nativeFileDownload(url);
}
},
),
];
if (filePath.split(".").last.toLowerCase() == "pdf") {
menuList.add(
SpeedDialChild(
child: Icon(
Icons.print,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Print",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
printDocument(url, filePath);
},
),
);
}
menuList.add(
SpeedDialChild(
child: Icon(
Icons.fullscreen,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Full Screen",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
context.pop();
context.pushNamed(
'fileViewer',
extra: FileViewArguments(
url,
filePath,
),
);
},
),
);
// }
if (hasAccessToDelete) {
menuList.add(
SpeedDialChild(
child: Icon(
Icons.delete,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Delete Document",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
deleteFilePopUp(filePath, fileID);
},
),
);
}
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: fileName,
windowBody: BuildFileView(
link: url,
path: filePath,
//pdfLink: '${AppEnviroment.baseFileUrl}/mih/$filePath',
),
menuOptions: menuList,
onWindowTapClose: () {
Navigator.pop(context);
},
),
);
}
void mihLoadingPopUp() {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
void initState() {
super.initState();
FlDownloader.initialize();
progressStream = FlDownloader.progressStream.listen((event) {
if (event.status == DownloadStatus.successful) {
setState(() {
progress = event.progress;
});
//Navigator.of(context).pop();
print("Progress $progress%: Success Downloading");
FlDownloader.openFile(filePath: event.filePath);
} else if (event.status == DownloadStatus.failed) {
print("Progress $progress%: Error Downloading");
} else if (event.status == DownloadStatus.running) {
print("Progress $progress%: Download Running");
}
});
}
@override
Widget build(BuildContext context) {
if (widget.files.isNotEmpty) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, int index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemCount: widget.files.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(
widget.files[index].file_name,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
subtitle: Text(
widget.files[index].insert_date,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
// trailing: Icon(
// Icons.arrow_forward,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
onTap: () async {
await getFileUrlApiCall(widget.files[index].file_path)
.then((urlHere) {
//print(url);
setState(() {
fileUrl = urlHere;
});
});
viewFilePopUp(
widget.files[index].file_name,
widget.files[index].file_path,
widget.files[index].idpatient_files,
fileUrl);
},
);
},
);
} else {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Stack(
alignment: AlignmentDirectional.center,
children: [
Icon(
MihIcons.mihRing,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
Icon(
Icons.file_present,
size: 110,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
],
),
const SizedBox(height: 10),
Text(
"No Documents have been added to this profile.",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
const SizedBox(height: 25),
Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
children: [
TextSpan(text: "Press "),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Icon(
Icons.menu,
size: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
TextSpan(text: " to add "),
widget.business != null
? TextSpan(text: " or generate a the first document")
: TextSpan(text: " the first document"),
],
),
),
),
],
),
);
// return const Center(
// child: Text(
// "No Documents Available",
// style: TextStyle(fontSize: 25, color: Colors.grey),
// textAlign: TextAlign.center,
// ),
// );
}
}
}

View File

@@ -0,0 +1,78 @@
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/icd10_code.dart.dart';
import 'package:flutter/material.dart';
class BuildICD10CodeList extends StatefulWidget {
final TextEditingController icd10CodeController;
final List<ICD10Code> icd10codeList;
const BuildICD10CodeList({
super.key,
required this.icd10CodeController,
required this.icd10codeList,
});
@override
State<BuildICD10CodeList> createState() => _BuildPatientsListState();
}
class _BuildPatientsListState extends State<BuildICD10CodeList> {
String baseAPI = AppEnviroment.baseApiUrl;
int counter = 0;
Widget displayCode(int index) {
String title = "ICD-10 Code: ${widget.icd10codeList[index].icd10}";
String description =
"Description: ${widget.icd10codeList[index].description}";
return ListTile(
title: Text(
title,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
subtitle: RichText(
text: TextSpan(
text: description,
style: DefaultTextStyle.of(context).style,
),
),
onTap: () {
//select code
setState(() {
widget.icd10CodeController.text =
"${widget.icd10codeList[index].icd10} - ${widget.icd10codeList[index].description}";
});
Navigator.of(context).pop();
},
);
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemCount: widget.icd10codeList.length,
itemBuilder: (context, index) {
//final patient = widget.patients[index].id_no.contains(widget.searchString);
//print(index);
return displayCode(index);
},
);
}
}

View File

@@ -0,0 +1,74 @@
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/medicine.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class BuildMedicinesList extends StatefulWidget {
final TextEditingController contoller;
final List<Medicine> medicines;
//final searchString;
const BuildMedicinesList({
super.key,
required this.contoller,
required this.medicines,
//required this.searchString,
});
@override
State<BuildMedicinesList> createState() => _BuildMedicinesListState();
}
class _BuildMedicinesListState extends State<BuildMedicinesList> {
int indexOn = 0;
@override
void dispose() {
// TODO: implement dispose
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView.separated(
separatorBuilder: (BuildContext context, int index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemCount: widget.medicines.length,
itemBuilder: (context, index) {
//final patient = widget.patients[index].id_no.contains(widget.searchString);
return ListTile(
title: Text(
widget.medicines[index].name,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
subtitle: Text(
"${widget.medicines[index].unit} - ${widget.medicines[index].form}",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
onTap: () {
setState(() {
widget.contoller.text =
"${widget.medicines[index].name}%t${widget.medicines[index].unit}%t${widget.medicines[index].form}";
Navigator.of(context).pop();
});
},
trailing: Icon(
Icons.arrow_forward,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
);
},
);
}
}

View File

@@ -0,0 +1,383 @@
import 'dart:convert';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_success_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/notes.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:flutter/material.dart';
import 'package:supertokens_flutter/http.dart' as http;
class BuildNotesList extends StatefulWidget {
final AppUser signedInUser;
final List<Note> notes;
final Patient selectedPatient;
final Business? business;
final BusinessUser? businessUser;
final String type;
const BuildNotesList({
super.key,
required this.notes,
required this.signedInUser,
required this.selectedPatient,
required this.business,
required this.businessUser,
required this.type,
});
@override
State<BuildNotesList> createState() => _BuildNotesListState();
}
class _BuildNotesListState extends State<BuildNotesList> {
final noteTitleController = TextEditingController();
final noteTextController = TextEditingController();
final businessNameController = TextEditingController();
final userNameController = TextEditingController();
final dateController = TextEditingController();
int indexOn = 0;
final baseAPI = AppEnviroment.baseApiUrl;
Future<void> deleteNoteApiCall(int NoteId) async {
var response = await http.delete(
Uri.parse("$baseAPI/notes/delete/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{"idpatient_notes": NoteId}),
);
//print("Here4");
//print(response.statusCode);
if (response.statusCode == 200) {
Navigator.of(context).pop();
Navigator.of(context).pop();
if (widget.business == null) {
Navigator.of(context).pushNamed('/patient-manager/patient',
arguments: PatientViewArguments(
widget.signedInUser,
widget.selectedPatient,
widget.businessUser,
widget.business,
"personal"));
} else {
Navigator.of(context).pushNamed('/patient-manager/patient',
arguments: PatientViewArguments(
widget.signedInUser,
widget.selectedPatient,
widget.businessUser,
widget.business,
"business"));
}
setState(() {});
String message =
"The note has been deleted successfully. This means it will no longer be visible on your and cannot be used for future appointments.";
successPopUp(message);
} else {
internetConnectionPopUp();
}
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
void successPopUp(String message) {
showDialog(
context: context,
builder: (context) {
return MIHSuccessMessage(
successType: "Success",
successMessage: message,
);
},
);
}
void deletePatientPopUp(int NoteId) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MIHDeleteMessage(
deleteType: "Note",
onTap: () {
deleteNoteApiCall(NoteId);
},
),
);
}
void viewNotePopUp(Note selectednote) {
setState(() {
noteTitleController.text = selectednote.note_name;
noteTextController.text = selectednote.note_text;
businessNameController.text = selectednote.doc_office;
userNameController.text = selectednote.doctor;
dateController.text = selectednote.insert_date;
});
bool hasAccessToDelete = false;
if (widget.type == "business" &&
selectednote.doc_office == widget.business!.Name) {
hasAccessToDelete = true;
}
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: "Note Details",
menuOptions: hasAccessToDelete
? [
SpeedDialChild(
child: Icon(
Icons.delete,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Delete Note",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
deletePatientPopUp(selectednote.idpatient_notes);
},
),
]
: null,
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: Column(
children: [
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: businessNameController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Office",
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: userNameController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Created By",
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: dateController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Created Date",
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: noteTitleController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Note Title",
),
const SizedBox(height: 10.0),
MihTextFormField(
height: 250,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: noteTextController,
multiLineInput: true,
requiredText: true,
readOnly: true,
hintText: "Note Details",
),
const SizedBox(height: 10.0),
],
),
),
);
}
@override
void dispose() {
noteTextController.dispose();
businessNameController.dispose();
userNameController.dispose();
dateController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (widget.notes.isNotEmpty) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, int index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemCount: widget.notes.length,
itemBuilder: (context, index) {
String notePreview = widget.notes[index].note_text;
if (notePreview.length > 30) {
notePreview = "${notePreview.substring(0, 30)} ...";
}
return ListTile(
title: Text(
"${widget.notes[index].note_name}\n${widget.notes[index].doc_office} - ${widget.notes[index].doctor}",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
subtitle: Text(
"${widget.notes[index].insert_date}:\n$notePreview",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
), //Text(widget.notes[index].note_text),
trailing: Icon(
Icons.arrow_forward,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
onTap: () {
viewNotePopUp(widget.notes[index]);
},
);
},
);
} else {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
const SizedBox(height: 50),
Stack(
alignment: AlignmentDirectional.center,
children: [
Icon(
MihIcons.mihRing,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
Icon(
Icons.article_outlined,
size: 110,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
],
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Text(
"No Notes have been added to this profile.",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
],
),
const SizedBox(height: 25),
Visibility(
visible: widget.business != null,
child: Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
children: [
TextSpan(text: "Press "),
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Icon(
Icons.menu,
size: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
TextSpan(text: " to add the first note"),
],
),
),
),
),
],
),
);
// return const Center(
// child: Text(
// "No Notes Available",
// style: TextStyle(fontSize: 25, color: Colors.grey),
// textAlign: TextAlign.center,
// ),
// );
}
}
}

View File

@@ -0,0 +1,52 @@
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class PatientProfileTile extends StatefulWidget {
final PatientViewArguments arguments;
final double packageSize;
const PatientProfileTile({
super.key,
required this.arguments,
required this.packageSize,
});
@override
State<PatientProfileTile> createState() => _PatientProfileTileState();
}
class _PatientProfileTileState extends State<PatientProfileTile> {
@override
Widget build(BuildContext context) {
return MihPackageTile(
authenticateUser: true,
onTap: () {
context.goNamed(
'patientProfile',
extra: widget.arguments,
);
// Navigator.of(context).pushNamed(
// '/patient-profile',
// arguments: widget.arguments,
// );
},
appName: "Patient Profile",
appIcon: Icon(
MihIcons.patientProfile,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// size: widget.packageSize,
),
iconSize: widget.packageSize,
primaryColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
secondaryColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
}
}

View File

@@ -0,0 +1,154 @@
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_claim_statement_generation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/claim_statement_file.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/components/claim_statement_window.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_claim_statement_files_list.dart';
import 'package:flutter/material.dart';
class PatientClaimOrStatement extends StatefulWidget {
final int patientIndex;
final Patient selectedPatient;
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final String type;
const PatientClaimOrStatement({
super.key,
required this.patientIndex,
required this.selectedPatient,
required this.signedInUser,
required this.business,
required this.businessUser,
required this.type,
});
@override
State<PatientClaimOrStatement> createState() =>
_PatientClaimOrStatementState();
}
class _PatientClaimOrStatementState extends State<PatientClaimOrStatement> {
late Future<List<ClaimStatementFile>> futueFiles;
late String env;
void claimOrStatementWindow() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => ClaimStatementWindow(
selectedPatient: widget.selectedPatient,
signedInUser: widget.signedInUser,
business: widget.business,
businessUser: widget.businessUser,
env: env,
),
);
}
@override
void initState() {
if (widget.business == null) {
futueFiles =
MIHClaimStatementGenerationApi.getClaimStatementFilesByPatient(
widget.signedInUser.app_id);
} else {
futueFiles =
MIHClaimStatementGenerationApi.getClaimStatementFilesByBusiness(
widget.business!.business_id);
}
if (AppEnviroment.getEnv() == "Prod") {
env = "Prod";
} else {
env = "Dev";
}
super.initState();
}
@override
Widget build(BuildContext context) {
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(),
);
}
Widget getBody() {
return Stack(
children: [
FutureBuilder(
future: futueFiles,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: Mihloadingcircle(),
);
} else if (snapshot.hasData) {
final filesList = snapshot.data!;
return Column(
children: [
//const Placeholder(),
BuildClaimStatementFileList(
files: filesList,
signedInUser: widget.signedInUser,
selectedPatient: widget.selectedPatient,
business: widget.business,
businessUser: widget.businessUser,
type: widget.type,
env: env,
),
],
);
} else {
return const Center(
child: Text("Error Loading Notes"),
);
}
},
),
Visibility(
visible: widget.type != "personal",
child: Positioned(
right: 10,
bottom: 10,
child: MihFloatingMenu(
icon: Icons.file_copy,
animatedIcon: AnimatedIcons.menu_close,
children: [
SpeedDialChild(
child: Icon(
Icons.add,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Generate Claim/ Statement",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
claimOrStatementWindow();
},
)
],
),
),
),
],
);
}
}

View File

@@ -0,0 +1,410 @@
import 'dart:convert';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_success_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/notes.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_notes_list.dart';
import 'package:flutter/material.dart';
import 'package:supertokens_flutter/http.dart' as http;
class PatientConsultation extends StatefulWidget {
final String patientAppId;
final Patient selectedPatient;
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final String type;
const PatientConsultation({
super.key,
required this.patientAppId,
required this.selectedPatient,
required this.signedInUser,
required this.business,
required this.businessUser,
required this.type,
});
@override
State<PatientConsultation> createState() => _PatientConsultationState();
}
class _PatientConsultationState extends State<PatientConsultation> {
late Future<List<Note>> futueNotes;
final titleController = TextEditingController();
final noteTextController = TextEditingController();
final officeController = TextEditingController();
final dateController = TextEditingController();
final doctorController = TextEditingController();
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
String endpoint = "${AppEnviroment.baseApiUrl}/notes/patients/";
final _formKey = GlobalKey<FormState>();
Future<List<Note>> fetchNotes(String endpoint) async {
final response = await http.get(Uri.parse(
"${AppEnviroment.baseApiUrl}/notes/patients/${widget.selectedPatient.app_id}"));
if (response.statusCode == 200) {
Iterable l = jsonDecode(response.body);
List<Note> notes =
List<Note>.from(l.map((model) => Note.fromJson(model)));
//print("Here notes");
return notes;
} else {
internetConnectionPopUp();
throw Exception('failed to load patients');
}
}
void addNotePopUp(double width) {
DateTime now = new DateTime.now();
DateTime date = new DateTime(now.year, now.month, now.day);
var title = "";
print("Business User: ${widget.businessUser}");
if (widget.businessUser?.title == "Doctor") {
title = "Dr.";
}
setState(() {
officeController.text = widget.business!.Name;
doctorController.text =
"$title ${widget.signedInUser.fname} ${widget.signedInUser.lname}";
dateController.text = date.toString().substring(0, 10);
});
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: "Add Note",
onWindowTapClose: () {
Navigator.pop(context);
titleController.clear();
noteTextController.clear();
},
windowBody: Padding(
padding:
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: width * 0.05)
: const EdgeInsets.symmetric(horizontal: 0),
child: Column(
children: [
MihForm(
formKey: _formKey,
formFields: [
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: officeController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Office",
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: doctorController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Created By",
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: dateController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Created Date",
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: titleController,
multiLineInput: false,
requiredText: true,
hintText: "Note Title",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10.0),
MihTextFormField(
height: 250,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: noteTextController,
multiLineInput: true,
requiredText: true,
hintText: "Note Details",
validator: (value) {
return MihValidationServices().validateLength(value, 512);
},
),
SizedBox(
height: 15,
child: ValueListenableBuilder(
builder:
(BuildContext context, int value, Widget? child) {
return Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
"$value",
style: TextStyle(
color: getNoteDetailLimitColor(),
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: 5),
Text(
"/512",
style: TextStyle(
color: getNoteDetailLimitColor(),
fontWeight: FontWeight.bold,
),
),
],
);
},
valueListenable: _counter,
),
),
const SizedBox(height: 15.0),
Center(
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
addPatientNoteAPICall();
Navigator.pop(context);
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"Add Note",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
],
),
),
),
);
}
Future<void> addPatientNoteAPICall() async {
// String title = "";
// if (widget.businessUser!.title == "Doctor") {
// title = "Dr.";
// }
var response = await http.post(
Uri.parse("${AppEnviroment.baseApiUrl}/notes/insert/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"note_name": titleController.text,
"note_text": noteTextController.text,
"doc_office": officeController.text,
"doctor": doctorController.text,
"app_id": widget.selectedPatient.app_id,
}),
);
if (response.statusCode == 201) {
setState(() {
futueNotes = fetchNotes(endpoint + widget.patientAppId.toString());
});
// Navigator.of(context)
// .pushNamed('/patient-manager', arguments: widget.userEmail);
String message =
"Your note has been successfully added to the patients medical record. You can now view it alongside their other important information.";
successPopUp(message);
} else {
internetConnectionPopUp();
}
}
bool isFieldsFilled() {
if (titleController.text.isEmpty ||
noteTextController.text.isEmpty ||
_counter.value >= 512) {
return false;
} else {
return true;
}
}
Color getNoteDetailLimitColor() {
if (_counter.value <= 512) {
return MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
} else {
return MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
}
}
void successPopUp(String message) {
showDialog(
context: context,
builder: (context) {
return MIHSuccessMessage(
successType: "Success",
successMessage: message,
);
},
);
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
@override
void dispose() {
titleController.dispose();
noteTextController.dispose();
doctorController.dispose();
dateController.dispose();
officeController.dispose();
super.dispose();
}
@override
void initState() {
futueNotes = fetchNotes(endpoint + widget.patientAppId);
noteTextController.addListener(() {
setState(() {
_counter.value = noteTextController.text.characters.length;
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(screenWidth),
);
}
Widget getBody(double width) {
return Stack(
children: [
MihSingleChildScroll(
child: FutureBuilder(
future: futueNotes,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: Mihloadingcircle(),
);
} else if (snapshot.hasData) {
final notesList = snapshot.data!;
return Column(children: [
BuildNotesList(
notes: notesList,
signedInUser: widget.signedInUser,
selectedPatient: widget.selectedPatient,
business: widget.business,
businessUser: widget.businessUser,
type: widget.type,
),
]);
} else {
return const Center(
child: Text("Error Loading Notes"),
);
}
},
),
),
Visibility(
visible: widget.type != "personal",
child: Positioned(
right: 10,
bottom: 10,
child: MihFloatingMenu(
icon: Icons.add,
animatedIcon: AnimatedIcons.menu_close,
children: [
SpeedDialChild(
child: Icon(
Icons.add,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Add Note",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
// addConsultationNotePopUp();
addNotePopUp(width);
},
)
],
),
),
),
],
);
}
}

View File

@@ -0,0 +1,674 @@
import 'dart:convert';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_date_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_success_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/files.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/components/prescip_input.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_files_list.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:supertokens_flutter/http.dart' as http;
class PatientDocuments extends StatefulWidget {
final int patientIndex;
final Patient selectedPatient;
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final String type;
const PatientDocuments({
super.key,
required this.patientIndex,
required this.selectedPatient,
required this.signedInUser,
required this.business,
required this.businessUser,
required this.type,
});
@override
State<PatientDocuments> createState() => _PatientDocumentsState();
}
class _PatientDocumentsState extends State<PatientDocuments> {
late Future<List<PFile>> futueFiles;
final selectedFileController = TextEditingController();
final startDateController = TextEditingController();
final endDateTextController = TextEditingController();
final retDateTextController = TextEditingController();
final medicineController = TextEditingController();
final quantityController = TextEditingController();
final dosageController = TextEditingController();
final timesDailyController = TextEditingController();
final noDaysController = TextEditingController();
final noRepeatsController = TextEditingController();
final outputController = TextEditingController();
late PlatformFile? selected;
final _formKey = GlobalKey<FormState>();
final _formKey2 = GlobalKey<FormState>();
late String env;
Future<void> submitDocUploadForm() async {
if (isFileFieldsFilled()) {
await uploadSelectedFile(selected);
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Input Error");
},
);
}
}
Future<List<PFile>> fetchFiles() async {
final response = await http.get(Uri.parse(
"${AppEnviroment.baseApiUrl}/patient_files/get/${widget.selectedPatient.app_id}"));
//print(response.statusCode);
//print(response.body);
if (response.statusCode == 200) {
Iterable l = jsonDecode(response.body);
List<PFile> files =
List<PFile>.from(l.map((model) => PFile.fromJson(model)));
return files;
} else {
internetConnectionPopUp();
throw Exception('failed to load patients');
}
}
Future<void> addPatientFileLocationToDB(PlatformFile? file) async {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
var fname = file!.name.replaceAll(RegExp(r' '), '-');
var filePath = "${widget.selectedPatient.app_id}/patient_files/$fname";
var response2 = await http.post(
Uri.parse("${AppEnviroment.baseApiUrl}/patient_files/insert/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"file_path": filePath,
"file_name": fname,
"app_id": widget.selectedPatient.app_id
}),
);
//print("here5");
//print(response2.statusCode);
if (response2.statusCode == 201) {
setState(() {
selectedFileController.clear();
futueFiles = fetchFiles();
});
// end loading circle
Navigator.of(context).pop();
String message =
"The file ${file.name.replaceAll(RegExp(r' '), '-')} has been successfully generated and added to ${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}'s record. You can now access and download it for their use.";
successPopUp(message);
} else {
internetConnectionPopUp();
}
}
Future<void> uploadSelectedFile(PlatformFile? file) async {
var response = await MihFileApi.uploadFile(
widget.selectedPatient.app_id,
env,
"patient_files",
file,
context,
);
if (response == 200) {
await addPatientFileLocationToDB(file);
} else {
internetConnectionPopUp();
}
}
Future<void> generateMedCert() async {
//start loading circle
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
DateTime now = DateTime.now();
// DateTime date = new DateTime(now.year, now.month, now.day);
String fileName =
"Med-Cert-${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}-${now.toString().substring(0, 19)}.pdf"
.replaceAll(RegExp(r' '), '-');
var response1 = await http.post(
Uri.parse("${AppEnviroment.baseApiUrl}/minio/generate/med-cert/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"app_id": widget.selectedPatient.app_id,
"env": env,
"patient_full_name":
"${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}",
"fileName": fileName,
"id_no": widget.selectedPatient.id_no,
"docfname":
"DR. ${widget.signedInUser.fname} ${widget.signedInUser.lname}",
"startDate": startDateController.text,
"busName": widget.business!.Name,
"busAddr": "*TO BE ADDED IN THE FUTURE*",
"busNo": widget.business!.contact_no,
"busEmail": widget.business!.bus_email,
"endDate": endDateTextController.text,
"returnDate": retDateTextController.text,
"logo_path": widget.business!.logo_path,
"sig_path": widget.businessUser!.sig_path,
}),
);
print(response1.statusCode);
if (response1.statusCode == 200) {
var response2 = await http.post(
Uri.parse("${AppEnviroment.baseApiUrl}/patient_files/insert/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"file_path":
"${widget.selectedPatient.app_id}/patient_files/$fileName",
"file_name": fileName,
"app_id": widget.selectedPatient.app_id
}),
);
//print(response2.statusCode);
if (response2.statusCode == 201) {
setState(() {
startDateController.clear();
endDateTextController.clear();
retDateTextController.clear();
futueFiles = fetchFiles();
});
// end loading circle
Navigator.of(context).pop();
Navigator.of(context).pop();
String message =
"The medical certificate $fileName has been successfully generated and added to ${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}'s record. You can now access and download it for their use.";
successPopUp(message);
} else {
internetConnectionPopUp();
}
} else {
internetConnectionPopUp();
}
}
void uploudFilePopUp(double width) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: "Upload File",
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: Padding(
padding:
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: width * 0.05)
: const EdgeInsets.symmetric(horizontal: 0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MihForm(
formKey: _formKey,
formFields: [
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: selectedFileController,
hintText: "Selected File",
requiredText: true,
readOnly: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
),
const SizedBox(width: 10),
MihButton(
onPressed: () async {
FilePickerResult? result =
await FilePicker.platform.pickFiles(
type: FileType.custom,
allowedExtensions: ['jpg', 'png', 'pdf'],
withData: true,
);
if (result == null) return;
final selectedFile = result.files.first;
print("Selected file: $selectedFile");
setState(() {
selected = selectedFile;
});
setState(() {
selectedFileController.text = selectedFile.name;
});
},
buttonColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
child: Text(
"Attach",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
const SizedBox(height: 20),
Center(
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
submitDocUploadForm();
// uploadSelectedFile(selected);
Navigator.pop(context);
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"Add File",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
],
),
),
),
);
}
void medCertPopUp() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: "Create Medical Certificate",
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: Column(
children: [
MihForm(
formKey: _formKey2,
formFields: [
MihDateField(
controller: startDateController,
labelText: "From",
required: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10.0),
MihDateField(
controller: endDateTextController,
labelText: "Up to Including",
required: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10.0),
MihDateField(
controller: retDateTextController,
labelText: "Return",
required: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
// Medcertinput(
// startDateController: startDateController,
// endDateTextController: endDateTextController,
// retDateTextController: retDateTextController,
// ),
const SizedBox(height: 15.0),
Center(
child: MihButton(
onPressed: () async {
if (_formKey2.currentState!.validate()) {
await generateMedCert();
//Navigator.pop(context);
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Generate",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
],
),
),
);
}
void prescritionPopUp() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: "Create Prescription",
onWindowTapClose: () {
medicineController.clear();
quantityController.text = "1";
dosageController.text = "1";
timesDailyController.text = "1";
noDaysController.text = "1";
noRepeatsController.text = "0";
Navigator.pop(context);
},
windowBody: Column(
children: [
PrescripInput(
medicineController: medicineController,
quantityController: quantityController,
dosageController: dosageController,
timesDailyController: timesDailyController,
noDaysController: noDaysController,
noRepeatsController: noRepeatsController,
outputController: outputController,
selectedPatient: widget.selectedPatient,
signedInUser: widget.signedInUser,
business: widget.business,
businessUser: widget.businessUser,
env: env,
),
],
),
),
);
}
bool isFileFieldsFilled() {
if (selectedFileController.text.isEmpty) {
return false;
} else {
return true;
}
}
bool isMedCertFieldsFilled() {
if (startDateController.text.isEmpty ||
endDateTextController.text.isEmpty ||
retDateTextController.text.isEmpty) {
return false;
} else {
return true;
}
}
Widget getMenu(double width) {
if (widget.type == "personal") {
return Positioned(
right: 10,
bottom: 10,
child: MihFloatingMenu(
icon: Icons.add,
animatedIcon: AnimatedIcons.menu_close,
children: [
SpeedDialChild(
child: Icon(
Icons.attach_file,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Attach Document",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
uploudFilePopUp(width);
},
)
],
),
);
} else {
return Positioned(
right: 10,
bottom: 10,
child: MihFloatingMenu(
icon: Icons.add,
animatedIcon: AnimatedIcons.menu_close,
children: [
SpeedDialChild(
child: Icon(
Icons.attach_file,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Add Document",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
uploudFilePopUp(width);
},
),
SpeedDialChild(
child: Icon(
Icons.sick_outlined,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Generate Medical Certificate",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
medCertPopUp();
},
),
SpeedDialChild(
child: Icon(
Icons.medication,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Generate Prescription",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
prescritionPopUp();
},
),
],
),
);
}
}
void successPopUp(String message) {
showDialog(
context: context,
builder: (context) {
return MIHSuccessMessage(
successType: "Success",
successMessage: message,
);
},
);
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
@override
void dispose() {
startDateController.dispose();
endDateTextController.dispose();
retDateTextController.dispose();
selectedFileController.dispose();
medicineController.dispose();
quantityController.dispose();
dosageController.dispose();
timesDailyController.dispose();
noDaysController.dispose();
noRepeatsController.dispose();
outputController.dispose();
super.dispose();
}
@override
void initState() {
futueFiles = fetchFiles();
if (AppEnviroment.getEnv() == "Prod") {
env = "Prod";
} else {
env = "Dev";
}
super.initState();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBody(screenWidth),
);
}
Widget getBody(double width) {
return Stack(
children: [
MihSingleChildScroll(
child: FutureBuilder(
future: futueFiles,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: Mihloadingcircle(),
);
} else if (snapshot.hasData) {
final filesList = snapshot.data!;
return Column(children: [
BuildFilesList(
files: filesList,
signedInUser: widget.signedInUser,
selectedPatient: widget.selectedPatient,
business: widget.business,
businessUser: widget.businessUser,
type: widget.type,
env: env,
),
]);
} else {
return const Center(
child: Text("Error Loading Notes"),
);
}
},
),
),
getMenu(width),
],
);
}
}

View File

@@ -0,0 +1,462 @@
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class PatientInfo extends StatefulWidget {
final AppUser signedInUser;
final Patient selectedPatient;
final String type;
const PatientInfo({
super.key,
required this.signedInUser,
required this.selectedPatient,
required this.type,
});
@override
State<PatientInfo> createState() => _PatientInfoState();
}
class _PatientInfoState extends State<PatientInfo> {
final idController = TextEditingController();
final fnameController = TextEditingController();
final lnameController = TextEditingController();
final cellController = TextEditingController();
final emailController = TextEditingController();
final medNoController = TextEditingController();
final medNameController = TextEditingController();
final medSchemeController = TextEditingController();
final addressController = TextEditingController();
final medAidController = TextEditingController();
final medMainMemController = TextEditingController();
final medAidCodeController = TextEditingController();
final _formKey = GlobalKey<FormState>();
double textFieldWidth = 300;
late String medAid;
late bool medAidPosition;
Widget getPatientDetailsField() {
return Center(
child: Wrap(
spacing: 10,
runSpacing: 10,
children: [
SizedBox(
width: textFieldWidth,
child: MihTextFormField(
// width: textFieldWidth,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: idController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "ID No.",
// validator: (value) {
// return MihValidationServices().isEmpty(value);
// },
),
),
SizedBox(
width: textFieldWidth,
child: MihTextFormField(
// width: textFieldWidth,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: fnameController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "First Name",
),
),
SizedBox(
width: textFieldWidth,
child: MihTextFormField(
// width: textFieldWidth,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: lnameController,
multiLineInput: false,
requiredText: true,
hintText: "Surname",
readOnly: true,
),
),
SizedBox(
width: textFieldWidth,
child: MihTextFormField(
// width: textFieldWidth,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: cellController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Cell No.",
),
),
SizedBox(
width: textFieldWidth,
child: MihTextFormField(
// width: textFieldWidth,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: emailController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Email",
),
),
SizedBox(
width: textFieldWidth,
child: MihTextFormField(
// width: textFieldWidth,
height: 100,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: addressController,
multiLineInput: true,
requiredText: true,
readOnly: true,
hintText: "Address",
),
),
],
),
);
}
Widget getMedAidDetailsFields() {
List<Widget> medAidDet = [];
medAidDet.add(
SizedBox(
width: textFieldWidth,
child: MihToggle(
hintText: "Medical Aid",
initialPostion: medAidPosition,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
secondaryFillColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
readOnly: true,
onChange: (value) {
if (value) {
setState(() {
medAidController.text = "Yes";
medAidPosition = value;
});
} else {
setState(() {
medAidController.text = "No";
medAidPosition = value;
});
}
},
),
// MihTextFormField(
// // width: textFieldWidth,
// fillColor: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// inputColor: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// controller: medAidController,
// multiLineInput: false,
// requiredText: true,
// readOnly: true,
// hintText: "Medical Aid",
// ),
),
);
bool req;
if (medAid == "Yes") {
req = true;
} else {
req = false;
}
medAidDet.addAll([
Visibility(
visible: req,
child: SizedBox(
width: textFieldWidth,
child: MihTextFormField(
// width: textFieldWidth,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: medMainMemController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Main Member",
),
),
),
Visibility(
visible: req,
child: SizedBox(
width: textFieldWidth,
child: MihTextFormField(
// width: textFieldWidth,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: medNoController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "No.",
),
),
),
Visibility(
visible: req,
child: SizedBox(
width: textFieldWidth,
child: MihTextFormField(
// width: textFieldWidth,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: medAidCodeController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Code",
),
),
),
Visibility(
visible: req,
child: SizedBox(
width: textFieldWidth,
child: MihTextFormField(
// width: textFieldWidth,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: medNameController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Name",
),
),
),
Visibility(
visible: req,
child: SizedBox(
width: textFieldWidth,
child: MihTextFormField(
// width: textFieldWidth,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: medSchemeController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Plan",
),
),
),
]);
return Center(
child: Wrap(
spacing: 10,
runSpacing: 10,
children: medAidDet,
),
);
}
@override
void dispose() {
idController.dispose();
fnameController.dispose();
lnameController.dispose();
cellController.dispose();
emailController.dispose();
medNameController.dispose();
medNoController.dispose();
medSchemeController.dispose();
addressController.dispose();
medAidController.dispose();
medMainMemController.dispose();
medAidCodeController.dispose();
super.dispose();
}
@override
void initState() {
setState(() {
idController.value = TextEditingValue(text: widget.selectedPatient.id_no);
fnameController.value =
TextEditingValue(text: widget.selectedPatient.first_name);
lnameController.value =
TextEditingValue(text: widget.selectedPatient.last_name);
cellController.value =
TextEditingValue(text: widget.selectedPatient.cell_no);
emailController.value =
TextEditingValue(text: widget.selectedPatient.email);
medNameController.value =
TextEditingValue(text: widget.selectedPatient.medical_aid_name);
medNoController.value =
TextEditingValue(text: widget.selectedPatient.medical_aid_no);
medSchemeController.value =
TextEditingValue(text: widget.selectedPatient.medical_aid_scheme);
addressController.value =
TextEditingValue(text: widget.selectedPatient.address);
medAidController.value =
TextEditingValue(text: widget.selectedPatient.medical_aid);
medMainMemController.value = TextEditingValue(
text: widget.selectedPatient.medical_aid_main_member);
medAidCodeController.value =
TextEditingValue(text: widget.selectedPatient.medical_aid_code);
medAid = widget.selectedPatient.medical_aid;
});
if (medAid == "Yes") {
medAidPosition = true;
} else {
medAidPosition = false;
}
super.initState();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageToolBody(
borderOn: false,
innerHorizontalPadding: 10,
bodyItem: getBody(screenWidth),
);
}
Widget getBody(double width) {
return Stack(
children: [
MihSingleChildScroll(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MihForm(
formKey: _formKey,
formFields: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
//crossAxisAlignment: ,
children: [
Text(
"Personal",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
]),
Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")),
const SizedBox(height: 10),
getPatientDetailsField(),
const SizedBox(height: 10),
Center(
child: Text(
"Medical Aid",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")),
const SizedBox(height: 10),
getMedAidDetailsFields(),
],
),
],
),
),
Visibility(
visible: widget.type == "personal",
child: Positioned(
right: 10,
bottom: 10,
child: MihFloatingMenu(
icon: Icons.add,
animatedIcon: AnimatedIcons.menu_close,
children: [
SpeedDialChild(
child: Icon(
Icons.edit,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
label: "Edit Profile",
labelBackgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
labelStyle: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
context.goNamed(
'patientProfileEdit',
extra: PatientEditArguments(
widget.signedInUser,
widget.selectedPatient,
),
);
},
)
],
),
),
),
],
);
}
}

View File

@@ -0,0 +1,659 @@
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_header.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_layout_builder.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class AddPatient extends StatefulWidget {
final AppUser signedInUser;
const AddPatient({
super.key,
required this.signedInUser,
});
@override
State<AddPatient> createState() => _AddPatientState();
}
class _AddPatientState extends State<AddPatient> {
final idController = TextEditingController();
final fnameController = TextEditingController();
final lnameController = TextEditingController();
final cellController = TextEditingController();
final emailController = TextEditingController();
final medNoController = TextEditingController();
final medNameController = TextEditingController();
final medSchemeController = TextEditingController();
final addressController = TextEditingController();
final medAidController = TextEditingController();
final medMainMemController = TextEditingController();
final medAidCodeController = TextEditingController();
late bool medAidPosition;
late bool medMainMemberPosition;
final baseAPI = AppEnviroment.baseApiUrl;
late int futureDocOfficeId;
//late bool medRequired;
final ValueNotifier<bool> medRequired = ValueNotifier(false);
final FocusNode _focusNode = FocusNode();
final _formKey = GlobalKey<FormState>();
bool isFieldsFilled() {
if (medRequired.value) {
if (idController.text.isEmpty ||
fnameController.text.isEmpty ||
lnameController.text.isEmpty ||
cellController.text.isEmpty ||
emailController.text.isEmpty ||
medNoController.text.isEmpty ||
medNameController.text.isEmpty ||
medSchemeController.text.isEmpty ||
addressController.text.isEmpty ||
medAidController.text.isEmpty ||
medMainMemController.text.isEmpty ||
medAidCodeController.text.isEmpty) {
return false;
} else {
return true;
}
} else {
if (idController.text.isEmpty ||
fnameController.text.isEmpty ||
lnameController.text.isEmpty ||
cellController.text.isEmpty ||
emailController.text.isEmpty ||
addressController.text.isEmpty ||
medAidController.text.isEmpty) {
return false;
} else {
return true;
}
}
}
Future<void> addPatientService() async {
int statusCode = await MihPatientServices().addPatientService(
idController.text,
fnameController.text,
lnameController.text,
emailController.text,
cellController.text,
medAidController.text,
medMainMemController.text,
medNoController.text,
medAidCodeController.text,
medNameController.text,
medSchemeController.text,
addressController.text,
widget.signedInUser,
);
if (statusCode == 201) {
String message =
"${fnameController.text} ${lnameController.text} patient profile has been successfully added!\n";
successPopUp("Successfully created Patient Profile", message);
} else {
internetConnectionPopUp();
}
}
void successPopUp(String title, String message) {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.check_circle_outline_rounded,
size: 150,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: title,
alertBody: Column(
children: [
Text(
message,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.pop();
context.goNamed(
'patientProfile',
extra: PatientViewArguments(
widget.signedInUser,
null,
null,
null,
"personal",
),
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
elevation: 10,
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
);
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
void messagePopUp(error) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(error),
);
},
);
}
void isRequired() {
//print("listerner triggered");
if (medAidController.text == "Yes") {
medRequired.value = true;
} else {
medRequired.value = false;
}
}
Widget displayForm(double width) {
return SingleChildScrollView(
child: Padding(
padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: width * 0.2)
: EdgeInsets.symmetric(horizontal: width * 0.075),
child: Column(
children: [
MihForm(
formKey: _formKey,
formFields: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Personal",
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25.0,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
],
),
Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: idController,
multiLineInput: false,
requiredText: true,
hintText: "ID No.",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: fnameController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "First Name",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: lnameController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Surname",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: cellController,
multiLineInput: false,
requiredText: true,
hintText: "Cell No.",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: emailController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Email",
validator: (value) {
return MihValidationServices().validateEmail(value);
},
),
const SizedBox(height: 10.0),
MihTextFormField(
height: 100,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: addressController,
multiLineInput: true,
requiredText: true,
hintText: "Address",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 15.0),
Center(
child: Text(
"Medical Aid Details",
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25.0,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
const SizedBox(height: 10.0),
MihToggle(
hintText: "Medical Aid",
initialPostion: medAidPosition,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
secondaryFillColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onChange: (value) {
if (value) {
setState(() {
medAidController.text = "Yes";
medAidPosition = value;
});
} else {
setState(() {
medAidController.text = "No";
medAidPosition = value;
});
}
},
),
ValueListenableBuilder(
valueListenable: medRequired,
builder: (BuildContext context, bool value, Widget? child) {
return Visibility(
visible: value,
child: Column(
children: [
const SizedBox(height: 10.0),
MihToggle(
hintText: "Main Member",
initialPostion: medMainMemberPosition,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
secondaryFillColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
onChange: (value) {
if (value) {
setState(() {
medMainMemController.text = "Yes";
medMainMemberPosition = value;
});
} else {
setState(() {
medMainMemController.text = "No";
medMainMemberPosition = value;
});
}
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: medNoController,
multiLineInput: false,
requiredText: true,
hintText: "No.",
validator: (validationValue) {
if (value) {
return MihValidationServices()
.isEmpty(validationValue);
}
return null;
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: medAidCodeController,
multiLineInput: false,
requiredText: true,
hintText: "Code",
validator: (validationValue) {
if (value) {
return MihValidationServices()
.isEmpty(validationValue);
}
return null;
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: medNameController,
multiLineInput: false,
requiredText: true,
hintText: "Name",
validator: (validationValue) {
if (value) {
return MihValidationServices()
.isEmpty(validationValue);
}
return null;
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: medSchemeController,
multiLineInput: false,
requiredText: true,
hintText: "Plan",
validator: (validationValue) {
if (value) {
return MihValidationServices()
.isEmpty(validationValue);
}
return null;
},
),
const SizedBox(height: 10.0),
],
),
);
},
),
const SizedBox(height: 20.0),
Center(
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
submitForm();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Add",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(height: 20.0),
],
),
],
),
),
);
}
void submitForm() {
addPatientService();
}
MIHAction getActionButton() {
return MIHAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
context.goNamed(
'mihHome',
extra: true,
);
FocusScope.of(context).unfocus();
},
);
}
MIHHeader getHeader() {
return const MIHHeader(
headerAlignment: MainAxisAlignment.center,
headerItems: [
Text(
"Set Up Patient Profile",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
],
);
}
MIHBody getBody(double width) {
return MIHBody(
borderOn: false,
bodyItems: [
KeyboardListener(
focusNode: _focusNode,
autofocus: true,
onKeyEvent: (event) async {
if (event is KeyDownEvent &&
event.logicalKey == LogicalKeyboardKey.enter) {
if (_formKey.currentState!.validate()) {
submitForm();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
}
},
child: displayForm(width),
),
],
);
}
@override
void dispose() {
idController.dispose();
fnameController.dispose();
lnameController.dispose();
cellController.dispose();
emailController.dispose();
medNoController.dispose();
medNameController.dispose();
medSchemeController.dispose();
addressController.dispose();
medAidController.dispose();
medAidCodeController.removeListener(isRequired);
medRequired.dispose();
medMainMemController.dispose();
medAidCodeController.dispose();
_focusNode.dispose();
super.dispose();
}
@override
void initState() {
medAidController.addListener(isRequired);
setState(() {
fnameController.text = widget.signedInUser.fname;
lnameController.text = widget.signedInUser.lname;
emailController.text = widget.signedInUser.email;
medAidPosition = false;
medMainMemberPosition = false;
medAidController.text = "No";
medMainMemController.text = "No";
});
super.initState();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MIHLayoutBuilder(
actionButton: getActionButton(),
header: getHeader(),
secondaryActionButton: null,
body: getBody(screenWidth),
actionDrawer: null,
secondaryActionDrawer: null,
bottomNavBar: null,
pullDownToRefresh: false,
onPullDown: () async {},
);
// return Scaffold(
// // appBar: const MIHAppBar(
// // barTitle: "Add Patient",
// // propicFile: null,
// // ),
// //drawer: MIHAppDrawer(signedInUser: widget.signedInUser),
// body: SafeArea(
// child: Stack(
// children: [
// KeyboardListener(
// focusNode: _focusNode,
// autofocus: true,
// onKeyEvent: (event) async {
// if (event is KeyDownEvent &&
// event.logicalKey == LogicalKeyboardKey.enter) {
// submitForm();
// }
// },
// child: displayForm(),
// ),
// Positioned(
// top: 10,
// left: 5,
// width: 50,
// height: 50,
// child: IconButton(
// onPressed: () {
// Navigator.of(context).pop();
// },
// icon: const Icon(Icons.arrow_back),
// ),
// )
// ],
// ),
// ),
// );
}
}

View File

@@ -0,0 +1,903 @@
import 'dart:convert';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_header.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_layout_builder.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:supertokens_flutter/supertokens.dart';
import 'package:supertokens_flutter/http.dart' as http;
class EditPatient extends StatefulWidget {
final Patient selectedPatient;
final AppUser signedInUser;
const EditPatient({
super.key,
required this.selectedPatient,
required this.signedInUser,
});
@override
State<EditPatient> createState() => _EditPatientState();
}
class _EditPatientState extends State<EditPatient> {
var idController = TextEditingController();
final fnameController = TextEditingController();
final lnameController = TextEditingController();
final cellController = TextEditingController();
final emailController = TextEditingController();
final medNoController = TextEditingController();
final medNameController = TextEditingController();
final medSchemeController = TextEditingController();
final addressController = TextEditingController();
final medAidController = TextEditingController();
final medMainMemController = TextEditingController();
final medAidCodeController = TextEditingController();
final baseAPI = AppEnviroment.baseApiUrl;
final docOfficeIdApiUrl = "${AppEnviroment.baseApiUrl}/users/profile/";
final apiUrlEdit = "${AppEnviroment.baseApiUrl}/patients/update/";
final apiUrlDelete = "${AppEnviroment.baseApiUrl}/patients/delete/";
final _formKey = GlobalKey<FormState>();
late bool medAidPosition;
late bool medMainMemberPosition;
late int futureDocOfficeId;
late String userEmail;
// bool medRequired = false;
final ValueNotifier<bool> medRequired = ValueNotifier(false);
late double width;
late double height;
final FocusNode _focusNode = FocusNode();
// Future getOfficeIdByUser(String endpoint) async {
// final response = await http.get(Uri.parse(endpoint));
// if (response.statusCode == 200) {
// String body = response.body;
// var decodedData = jsonDecode(body);
// AppUser u = AppUser.fromJson(decodedData as Map<String, dynamic>);
// setState(() {
// //futureDocOfficeId = u.docOffice_id;
// //print(futureDocOfficeId);
// });
// } else {
// internetConnectionPopUp();
// throw Exception('failed to load patients');
// }
// }
Future<void> updatePatientApiCall() async {
var statusCode = await MihPatientServices().updatePatientService(
widget.selectedPatient.app_id,
idController.text,
fnameController.text,
lnameController.text,
emailController.text,
cellController.text,
medAidController.text,
medMainMemController.text,
medNoController.text,
medAidCodeController.text,
medNameController.text,
medSchemeController.text,
addressController.text,
);
if (statusCode == 200) {
successPopUp(
"Successfully Updated Profile!",
"${fnameController.text} ${lnameController.text}'s information has been updated successfully! Their medical records and details are now current.",
);
} else {
MihAlertServices().errorAlert(
"Error Updating Profile",
"There was an error updating your profile. Please try again later.",
context,
);
}
// var response = await http.put(
// Uri.parse(apiUrlEdit),
// headers: <String, String>{
// "Content-Type": "application/json; charset=UTF-8"
// },
// body: jsonEncode(<String, dynamic>{
// "id_no": idController.text,
// "first_name": fnameController.text,
// "last_name": lnameController.text,
// "email": emailController.text,
// "cell_no": cellController.text,
// "medical_aid": medAidController.text,
// "medical_aid_main_member": medMainMemController.text,
// "medical_aid_no": medNoController.text,
// "medical_aid_code": medAidCodeController.text,
// "medical_aid_name": medNameController.text,
// "medical_aid_scheme": medSchemeController.text,
// "address": addressController.text,
// "app_id": widget.selectedPatient.app_id,
// }),
// );
// print(response.statusCode);
// if (response.statusCode == 200) {
// Navigator.of(context).pop();
// Navigator.of(context).pop();
// Navigator.of(context).pushNamed('/patient-profile',
// arguments: PatientViewArguments(
// widget.signedInUser, null, null, null, "personal"));
// //Navigator.of(context).pushNamed('/');
// String message =
// "${fnameController.text} ${lnameController.text}'s information has been updated successfully! Their medical records and details are now current.";
// successPopUp(message);
// } else {
// internetConnectionPopUp();
// }
}
void successPopUp(String title, String message) {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.check_circle_outline_rounded,
size: 150,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: title,
alertBody: Column(
children: [
Text(
message,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.goNamed(
"patientProfile",
extra: PatientViewArguments(
widget.signedInUser,
widget.selectedPatient,
null,
null,
"personal",
),
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
elevation: 10,
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
// return MIHSuccessMessage(
// successType: "Success",
// successMessage: message,
// );
},
);
}
Future<void> deletePatientApiCall() async {
//print("Here1");
//userEmail = getLoginUserEmail() as String;
//print(userEmail);
//print("Here2");
//await getOfficeIdByUser(docOfficeIdApiUrl + userEmail);
//print("Office ID: ${futureDocOfficeId.toString()}");
//print("OPatient ID No: ${idController.text}");
//print("Here3");
var response = await http.delete(
Uri.parse(apiUrlDelete),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(
<String, dynamic>{"app_id": widget.selectedPatient.app_id}),
);
//print("Here4");
//print(response.statusCode);
if (response.statusCode == 200) {
Navigator.of(context).pop();
Navigator.of(context).pop();
Navigator.of(context).popAndPushNamed('/patient-profile',
arguments: PatientViewArguments(
widget.signedInUser, null, null, null, "personal"));
String message =
"${fnameController.text} ${lnameController.text}'s record has been deleted successfully. This means it will no longer be visible in patient manager and cannot be used for future appointments.";
successPopUp("Error", message);
} else {
internetConnectionPopUp();
}
}
Future<void> getLoginUserEmail() async {
var uid = await SuperTokens.getUserId();
var response = await http.get(Uri.parse("$baseAPI/user/$uid"));
if (response.statusCode == 200) {
var user = jsonDecode(response.body);
userEmail = user["email"];
}
}
void messagePopUp(error) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(error),
);
},
);
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
void deletePatientPopUp() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => Dialog(
child: Stack(
children: [
Container(
padding: const EdgeInsets.all(10.0),
width: 700.0,
height: (height / 3) * 2,
decoration: BoxDecoration(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(25.0),
border: Border.all(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 5.0),
),
child: SingleChildScrollView(
child: Column(
//mainAxisSize: MainAxisSize.max,
children: [
Icon(
Icons.warning_amber_rounded,
size: 100,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(height: 15),
Text(
"Are you sure you want to delete this?",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 25.0,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Text(
"This action is permanent! Deleting ${fnameController.text} ${lnameController.text} will remove him\\her from your account. You won't be able to recover it once it's gone.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 15),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Text(
"Here's what you'll be deleting:",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: SizedBox(
width: 450,
child: Text(
"1) Patient Profile Information.\n2) Patient Notes\n3) Patient Files.",
textAlign: TextAlign.left,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
),
),
MihButton(
onPressed: deletePatientApiCall,
buttonColor: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"Delete",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
Positioned(
top: 5,
right: 5,
width: 50,
height: 50,
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.close,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 35,
),
),
),
],
),
),
);
}
bool isFieldsFilled() {
if (medRequired.value) {
if (idController.text.isEmpty ||
fnameController.text.isEmpty ||
lnameController.text.isEmpty ||
cellController.text.isEmpty ||
emailController.text.isEmpty ||
medNoController.text.isEmpty ||
medNameController.text.isEmpty ||
medSchemeController.text.isEmpty ||
addressController.text.isEmpty ||
medAidController.text.isEmpty ||
medMainMemController.text.isEmpty ||
medAidCodeController.text.isEmpty) {
return false;
} else {
return true;
}
} else {
if (idController.text.isEmpty ||
fnameController.text.isEmpty ||
lnameController.text.isEmpty ||
cellController.text.isEmpty ||
emailController.text.isEmpty ||
addressController.text.isEmpty ||
medAidController.text.isEmpty) {
return false;
} else {
return true;
}
}
}
void isRequired() {
print("listerner triggered");
if (medAidController.text == "Yes") {
medRequired.value = true;
} else if (medAidController.text == "No") {
medRequired.value = false;
} else {
//print("here");
}
}
Widget displayForm(double width) {
return SingleChildScrollView(
child: Padding(
padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: width * 0.2)
: EdgeInsets.symmetric(horizontal: width * 0.075),
child: Column(
children: [
MihForm(
formKey: _formKey,
formFields: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Personal",
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25.0,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
],
),
Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: idController,
multiLineInput: false,
requiredText: true,
hintText: "ID No.",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: fnameController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "First Name",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: lnameController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Surname",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: cellController,
multiLineInput: false,
requiredText: true,
hintText: "Cell No.",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: emailController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Email",
validator: (value) {
return MihValidationServices().validateEmail(value);
},
),
const SizedBox(height: 10.0),
MihTextFormField(
height: 100,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
controller: addressController,
multiLineInput: true,
requiredText: true,
hintText: "Address",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 15.0),
Center(
child: Text(
"Medical Aid Details",
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25.0,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
const SizedBox(height: 10.0),
MihToggle(
hintText: "Medical Aid",
initialPostion: medAidPosition,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
secondaryFillColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onChange: (value) {
if (value) {
setState(() {
medAidController.text = "Yes";
medAidPosition = value;
});
} else {
setState(() {
medAidController.text = "No";
medAidPosition = value;
});
}
},
),
ValueListenableBuilder(
valueListenable: medRequired,
builder: (BuildContext context, bool value, Widget? child) {
return Visibility(
visible: value,
child: Column(
children: [
const SizedBox(height: 10.0),
MihToggle(
hintText: "Main Member",
initialPostion: medMainMemberPosition,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
secondaryFillColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
onChange: (value) {
if (value) {
setState(() {
medMainMemController.text = "Yes";
medMainMemberPosition = value;
});
} else {
setState(() {
medMainMemController.text = "No";
medMainMemberPosition = value;
});
}
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: medNoController,
multiLineInput: false,
requiredText: true,
hintText: "No.",
validator: (validationValue) {
if (value) {
return MihValidationServices()
.isEmpty(validationValue);
}
return null;
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: medAidCodeController,
multiLineInput: false,
requiredText: true,
hintText: "Code",
validator: (validationValue) {
if (value) {
return MihValidationServices()
.isEmpty(validationValue);
}
return null;
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: medNameController,
multiLineInput: false,
requiredText: true,
hintText: "Name",
validator: (validationValue) {
if (value) {
return MihValidationServices()
.isEmpty(validationValue);
}
return null;
},
),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: medSchemeController,
multiLineInput: false,
requiredText: true,
hintText: "Plan",
validator: (validationValue) {
if (value) {
return MihValidationServices()
.isEmpty(validationValue);
}
return null;
},
),
const SizedBox(height: 10.0),
],
),
);
},
),
const SizedBox(height: 20.0),
Center(
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
submitForm();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Update",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
const SizedBox(height: 20.0),
],
),
],
),
),
);
}
void submitForm() {
updatePatientApiCall();
}
MIHAction getActionButton() {
return MIHAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
context.goNamed(
'patientProfile',
extra: PatientViewArguments(
widget.signedInUser,
null,
null,
null,
"personal",
),
);
// Navigator.of(context).pop();
},
);
}
MIHHeader getHeader() {
return const MIHHeader(
headerAlignment: MainAxisAlignment.center,
headerItems: [
Text(
"Edit Patient Details",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
],
);
}
MIHBody getBody(double width) {
return MIHBody(
borderOn: false,
bodyItems: [
KeyboardListener(
focusNode: _focusNode,
autofocus: true,
onKeyEvent: (event) async {
if (event is KeyDownEvent &&
event.logicalKey == LogicalKeyboardKey.enter) {
if (_formKey.currentState!.validate()) {
submitForm();
} else {
MihAlertServices().formNotFilledCompletely(context);
}
}
},
child: displayForm(width),
),
],
);
}
@override
void dispose() {
idController.dispose();
fnameController.dispose();
lnameController.dispose();
cellController.dispose();
emailController.dispose();
medNoController.dispose();
medNameController.dispose();
medSchemeController.dispose();
addressController.dispose();
medAidController.dispose();
medAidCodeController.removeListener(isRequired);
medMainMemController.dispose();
medAidCodeController.dispose();
medRequired.dispose();
_focusNode.dispose();
super.dispose();
}
@override
void initState() {
getLoginUserEmail();
medAidController.addListener(isRequired);
setState(() {
idController.text = widget.selectedPatient.id_no;
fnameController.text = widget.selectedPatient.first_name;
lnameController.text = widget.selectedPatient.last_name;
cellController.text = widget.selectedPatient.cell_no;
emailController.text = widget.selectedPatient.email;
medNameController.text = widget.selectedPatient.medical_aid_name;
medNoController.text = widget.selectedPatient.medical_aid_no;
medSchemeController.text = widget.selectedPatient.medical_aid_scheme;
addressController.text = widget.selectedPatient.address;
medAidController.text = widget.selectedPatient.medical_aid;
medMainMemController.text =
widget.selectedPatient.medical_aid_main_member;
medAidCodeController.text = widget.selectedPatient.medical_aid_code;
});
if (medAidController.text == "Yes") {
medAidPosition = true;
} else {
medAidPosition = false;
medAidController.text = "No";
}
if (medMainMemController.text == "Yes") {
medMainMemberPosition = true;
} else {
medMainMemberPosition = false;
medMainMemController.text = "No";
}
super.initState();
}
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
setState(() {
width = size.width;
height = size.height;
});
return MIHLayoutBuilder(
actionButton: getActionButton(),
header: getHeader(),
secondaryActionButton: null,
body: getBody(width),
actionDrawer: null,
secondaryActionDrawer: null,
bottomNavBar: null,
pullDownToRefresh: false,
onPullDown: () async {},
);
}
}

View File

@@ -0,0 +1,130 @@
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/package_tools/patient_claim_or_statement.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/package_tools/patient_consultation.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/package_tools/patient_documents.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/package_tools/patient_info.dart';
import 'package:flutter/material.dart';
class PatientProfile extends StatefulWidget {
final PatientViewArguments arguments;
const PatientProfile({
super.key,
required this.arguments,
});
@override
State<PatientProfile> createState() => _PatientProfileState();
}
class _PatientProfileState extends State<PatientProfile> {
int _selcetedIndex = 0;
@override
Widget build(BuildContext context) {
return MihPackage(
appActionButton: getAction(),
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
},
);
}
MihPackageAction getAction() {
return MihPackageAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
if (widget.arguments.type == "business") {
context.pop();
} else {
context.goNamed(
'mihHome',
);
}
FocusScope.of(context).unfocus();
},
);
}
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.perm_identity)] = () {
setState(() {
_selcetedIndex = 0;
});
};
temp[const Icon(Icons.article_outlined)] = () {
setState(() {
_selcetedIndex = 1;
});
};
temp[const Icon(Icons.file_present)] = () {
setState(() {
_selcetedIndex = 2;
});
};
temp[const Icon(Icons.file_open_outlined)] = () {
setState(() {
_selcetedIndex = 3;
});
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
PatientInfo(
signedInUser: widget.arguments.signedInUser,
selectedPatient: widget.arguments.selectedPatient!,
type: widget.arguments.type,
),
PatientConsultation(
patientAppId: widget.arguments.selectedPatient!.app_id,
selectedPatient: widget.arguments.selectedPatient!,
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
businessUser: widget.arguments.businessUser,
type: widget.arguments.type,
),
PatientDocuments(
patientIndex: widget.arguments.selectedPatient!.idpatients,
selectedPatient: widget.arguments.selectedPatient!,
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
businessUser: widget.arguments.businessUser,
type: widget.arguments.type,
),
PatientClaimOrStatement(
patientIndex: widget.arguments.selectedPatient!.idpatients,
selectedPatient: widget.arguments.selectedPatient!,
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
businessUser: widget.arguments.businessUser,
type: widget.arguments.type,
),
];
return toolBodies;
}
List<String> getToolTitle() {
List<String> toolTitles = [
"Details",
"Notes",
"Documents",
"Claims",
];
return toolTitles;
}
}