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,624 @@
import 'dart:convert';
import 'package:go_router/go_router.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_service_calls.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_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_success_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_warning_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:flutter/material.dart';
import 'package:supertokens_flutter/http.dart' as http;
class BuildMihPatientSearchList extends StatefulWidget {
final List<Patient> patients;
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final bool personalSelected;
const BuildMihPatientSearchList({
super.key,
required this.patients,
required this.signedInUser,
required this.business,
required this.businessUser,
required this.personalSelected,
});
@override
State<BuildMihPatientSearchList> createState() => _BuildPatientsListState();
}
class _BuildPatientsListState extends State<BuildMihPatientSearchList> {
TextEditingController dateController = TextEditingController();
TextEditingController timeController = TextEditingController();
TextEditingController idController = TextEditingController();
TextEditingController fnameController = TextEditingController();
TextEditingController lnameController = TextEditingController();
TextEditingController accessStatusController = TextEditingController();
final baseAPI = AppEnviroment.baseApiUrl;
Future<void> addPatientAccessAPICall(int index) async {
var response = await http.post(
Uri.parse("$baseAPI/access-requests/insert/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"business_id": widget.business!.business_id,
"app_id": widget.patients[index].app_id,
"date": dateController.text,
"time": timeController.text,
"access": "pending",
}),
);
if (response.statusCode == 201) {
// Navigator.pushNamed(context, '/patient-manager/patient',
// arguments: widget.signedInUser);
String message =
"The appointment has been successfully booked!\n\nAn approval request as been sent to the patient.Once the access request has been approved, you will be able to access the patients profile. ou can check the status of your request in patient queue under the appointment.";
// "${fnameController.text} ${lnameController.text} patient profiole has been successfully added!\n";
Navigator.pop(context);
Navigator.pop(context);
setState(() {
dateController.text = "";
timeController.text = "";
});
Navigator.of(context).pushNamed(
'/patient-manager',
arguments: BusinessArguments(
widget.signedInUser,
widget.businessUser,
widget.business,
),
);
successPopUp(message);
addAccessReviewNotificationAPICall(index);
} else {
internetConnectionPopUp();
}
}
Future<void> addAccessReviewNotificationAPICall(int index) async {
var response = await http.post(
Uri.parse("$baseAPI/notifications/insert/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"app_id": widget.patients[index].app_id,
"notification_type": "New Appointment Booked",
"notification_message":
"A new Appointment has been booked by ${widget.business!.Name} for the ${dateController.text} ${timeController.text}. Please approve the Access Review request.",
"action_path": "/mih-access",
}),
);
if (response.statusCode == 201) {
// Navigator.pushNamed(context, '/patient-manager/patient',
// arguments: widget.signedInUser);
} 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 noAccessWarning() {
showDialog(
context: context,
builder: (context) {
return const MIHWarningMessage(warningType: "No Access");
},
);
}
Future<bool> hasAccessToProfile(int index) async {
var hasAccess = false;
await MIHApiCalls.checkBusinessAccessToPatient(
widget.business!.business_id, widget.patients[index].app_id)
.then((results) {
if (results.isEmpty) {
setState(() {
hasAccess = false;
});
} else if (results[0].status == "approved") {
setState(() {
hasAccess = true;
});
} else {
setState(() {
hasAccess = false;
});
}
});
return hasAccess;
}
Future<String> getAccessStatusOfProfile(int index) async {
var accessStatus = "";
await MIHApiCalls.checkBusinessAccessToPatient(
widget.business!.business_id, widget.patients[index].app_id)
.then((results) {
if (results.isEmpty) {
setState(() {
accessStatus = "";
});
} else {
setState(() {
accessStatus = results[0].status;
});
}
});
return accessStatus;
}
void patientProfileChoicePopUp(int index) async {
var hasAccess = false;
String accessStatus = "";
await hasAccessToProfile(index).then((result) {
setState(() {
hasAccess = result;
});
});
await getAccessStatusOfProfile(index).then((result) {
setState(() {
accessStatus = result;
});
});
if (accessStatus == "") {
accessStatus = "No Access";
}
var idStars = '*' * (13 - 6);
String startedOutPatientIdNo =
"${widget.patients[index].id_no.substring(0, 6)}$idStars";
setState(() {
idController.text = startedOutPatientIdNo;
fnameController.text = widget.patients[index].first_name;
lnameController.text = widget.patients[index].last_name;
accessStatusController.text = accessStatus.toUpperCase();
});
//print(accessStatus);
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: "Patient Profile",
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: Column(
children: [
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,
readOnly: 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: accessStatusController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Access Status",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 20.0),
Visibility(
visible: !hasAccess,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Important Notice: Requesting Patient Profile Access",
style: TextStyle(
fontWeight: FontWeight.bold,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
Text(
"You are about to request access to a patient's profile. Please be aware of the following important points:",
style: TextStyle(
fontWeight: FontWeight.normal,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
SizedBox(
width: 600,
child: Text(
"1. Permanent Access: Once the patient accepts your access request, it will become permanent.",
style: TextStyle(
fontWeight: FontWeight.normal,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
SizedBox(
width: 600,
child: Text(
"2. Shared Information: Any updates you make to the patient's profile will be visible to others who have access to the profile.",
style: TextStyle(
fontWeight: FontWeight.normal,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
SizedBox(
width: 600,
child: Text(
"3. Irreversible Access: Once granted, you cannot revoke your access to the patient's profile.",
style: TextStyle(
fontWeight: FontWeight.normal,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
Text(
"By pressing the \"Request Access\" button you accept the above terms.\n",
style: TextStyle(
fontWeight: FontWeight.bold,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
],
),
),
// const SizedBox(height: 15.0),
Center(
child: Wrap(
alignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
runSpacing: 10,
spacing: 10,
children: [
Visibility(
visible: hasAccess,
child: Center(
child: MihButton(
onPressed: () {
if (hasAccess) {
context.pop();
context.pushNamed('patientManagerPatient',
extra: PatientViewArguments(
widget.signedInUser,
widget.patients[index],
widget.businessUser,
widget.business,
"business",
));
// Navigator.of(context)
// .pushNamed('/patient-manager/patient',
// arguments: PatientViewArguments(
// widget.signedInUser,
// widget.patients[index],
// widget.businessUser,
// widget.business,
// "business",
// ));
} else {
noAccessWarning();
}
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"View Profile",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
),
Visibility(
visible: !hasAccess && accessStatus == "No Access",
child: Center(
child: MihButton(
onPressed: () {
MIHApiCalls.addPatientAccessAPICall(
widget.business!.business_id,
widget.patients[index].app_id,
"patient",
widget.business!.Name,
widget.personalSelected,
BusinessArguments(
widget.signedInUser,
widget.businessUser,
widget.business,
),
context,
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"Request Access",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
),
Visibility(
visible: !hasAccess && accessStatus == "declined",
child: Center(
child: MihButton(
onPressed: () {
MIHApiCalls.reapplyPatientAccessAPICall(
widget.business!.business_id,
widget.patients[index].app_id,
widget.personalSelected,
BusinessArguments(
widget.signedInUser,
widget.businessUser,
widget.business,
),
context,
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"Re-apply",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
),
Visibility(
visible: !hasAccess && accessStatus == "pending",
child: const SizedBox(
width: 500,
//height: 50,
child: Text(
"Patient has not approved access to their profile. Once access has been approved you can book and appointment or view their profile."),
),
),
],
),
),
],
),
),
);
}
Widget isMainMember(int index) {
//var matchRE = RegExp(r'^[a-z]+$');
// var firstLetterFName = widget.patients[index].first_name[0];
// var firstLetterLName = widget.patients[index].last_name[0];
// var fnameStar = '*' * 8;
// var lnameStar = '*' * 8;
if (widget.patients[index].medical_aid_main_member == "Yes") {
return Row(
mainAxisSize: MainAxisSize.max,
children: [
Text(
// "$firstLetterFName$fnameStar $firstLetterLName$lnameStar",
"${widget.patients[index].first_name} ${widget.patients[index].last_name}",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
const SizedBox(
width: 10,
),
Icon(
Icons.star_border_rounded,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
],
);
} else {
return Text(
// "$firstLetterFName$fnameStar $firstLetterLName$lnameStar",
"${widget.patients[index].first_name} ${widget.patients[index].last_name}",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
);
}
}
Widget hasMedicalAid(int index) {
var medAidNoStar = '*' * 8;
var idStars = '*' * (13 - 6);
String startedOutPatientIdNo =
"${widget.patients[index].id_no.substring(0, 6)}$idStars";
if (widget.patients[index].medical_aid == "Yes") {
return ListTile(
title: isMainMember(index),
subtitle: Text(
"ID No.: $startedOutPatientIdNo\nMedical Aid No.: $medAidNoStar",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
onTap: () {
patientProfileChoicePopUp(index);
// setState(() {
// appointmentPopUp(index);
// // Add popup to add patienmt to queue
// // Navigator.of(context).pushNamed('/patient-manager/patient',
// // arguments: PatientViewArguments(
// // widget.signedInUser, widget.patients[index], "business"));
// });
},
trailing: Icon(
Icons.arrow_forward,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
);
} else {
return ListTile(
title: isMainMember(index),
subtitle: Text(
"ID No.: $startedOutPatientIdNo\nMedical Aid No.: $medAidNoStar",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
onTap: () {
patientProfileChoicePopUp(index);
// setState(() {
// appointmentPopUp(index);
// // Navigator.of(context).pushNamed('/patient-manager/patient',
// // arguments: PatientViewArguments(
// // widget.signedInUser, widget.patients[index], "business"));
// });
},
trailing: Icon(
Icons.add,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
);
}
}
@override
void dispose() {
dateController.dispose();
timeController.dispose();
idController.dispose();
fnameController.dispose();
lnameController.dispose();
accessStatusController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemCount: widget.patients.length,
itemBuilder: (context, index) {
//final patient = widget.patients[index].id_no.contains(widget.searchString);
//print(index);
return hasMedicalAid(index);
},
);
}
}

View File

@@ -0,0 +1,573 @@
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_service_calls.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_calendar_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_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_time_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_warning_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/patient_access.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:flutter/material.dart';
class BuildMyPatientListList extends StatefulWidget {
final List<PatientAccess> patientAccesses;
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
const BuildMyPatientListList({
super.key,
required this.patientAccesses,
required this.signedInUser,
required this.business,
required this.businessUser,
});
@override
State<BuildMyPatientListList> createState() => _BuildPatientsListState();
}
class _BuildPatientsListState extends State<BuildMyPatientListList> {
TextEditingController dateController = TextEditingController();
TextEditingController timeController = TextEditingController();
TextEditingController idController = TextEditingController();
TextEditingController fnameController = TextEditingController();
TextEditingController lnameController = TextEditingController();
final _formKey = GlobalKey<FormState>();
final baseAPI = AppEnviroment.baseApiUrl;
Future<void> submitApointment(int index) async {
//To-Do: Add the appointment to the database
// print("To-Do: Add the appointment to the database");
String description =
"Date: ${dateController.text}\nTime: ${timeController.text}\n";
description += "Medical Practice: ${widget.business!.Name}\n";
description += "Contact Number: ${widget.business!.contact_no}";
int statusCode;
statusCode = await MihMzansiCalendarApis.addPatientAppointment(
widget.signedInUser,
false,
widget.patientAccesses[index].app_id,
BusinessArguments(
widget.signedInUser,
widget.businessUser,
widget.business,
),
"${widget.patientAccesses[index].fname} ${widget.patientAccesses[index].lname} - Doctors Visit",
description,
dateController.text,
timeController.text,
context,
);
if (statusCode == 201) {
context.pop();
successPopUp("Successfully Added Appointment",
"You appointment has been successfully added to your calendar.");
} else {
internetConnectionPopUp();
}
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(
errorType: "Internet Connection",
);
},
);
}
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.pop();
setState(() {
dateController.clear();
timeController.clear();
idController.clear();
fnameController.clear();
lnameController.clear();
});
},
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"),
);
},
);
}
bool isAppointmentFieldsFilled() {
if (dateController.text.isEmpty || timeController.text.isEmpty) {
return false;
} else {
return true;
}
}
void appointmentPopUp(int index, double width) {
var firstLetterFName = widget.patientAccesses[index].fname;
var firstLetterLName = widget.patientAccesses[index].lname;
setState(() {
idController.text = widget.patientAccesses[index].id_no;
fnameController.text = firstLetterFName;
lnameController.text = firstLetterLName;
});
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: "Patient Appointment",
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: Padding(
padding:
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: width * 0.056)
: 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: idController,
multiLineInput: false,
requiredText: true,
readOnly: 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),
MihDateField(
controller: dateController,
labelText: "Date",
required: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10),
MihTimeField(
controller: timeController,
labelText: "Time",
required: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 30.0),
Center(
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
bool filled = isAppointmentFieldsFilled();
if (filled) {
submitApointment(index);
} 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(
"Book Appointment",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
],
),
),
),
);
}
void noAccessWarning(int index) {
if (widget.patientAccesses[index].status == "pending") {
showDialog(
context: context,
builder: (context) {
return const MIHWarningMessage(warningType: "No Access");
},
);
} else {
showDialog(
context: context,
builder: (context) {
return const MIHWarningMessage(warningType: "Access Declined");
},
);
}
}
bool hasAccessToProfile(int index) {
var hasAccess = false;
if (widget.patientAccesses[index].status == "approved") {
hasAccess = true;
} else {
hasAccess = false;
}
return hasAccess;
}
void patientProfileChoicePopUp(
int index, Patient? patientProfile, double width) async {
var firstLetterFName = widget.patientAccesses[index].fname;
var firstLetterLName = widget.patientAccesses[index].lname;
setState(() {
idController.text = widget.patientAccesses[index].id_no;
fnameController.text = firstLetterFName;
lnameController.text = firstLetterLName;
});
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: "Patient Profile",
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(
children: [
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,
readOnly: 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: 30.0),
Center(
child: Wrap(
runSpacing: 10,
spacing: 10,
children: [
MihButton(
onPressed: () {
appointmentPopUp(index, width);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"Book Appointment",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
MihButton(
onPressed: () {
context.pop();
context.pushNamed('patientManagerPatient',
extra: PatientViewArguments(
widget.signedInUser,
patientProfile,
widget.businessUser,
widget.business,
"business",
));
// Navigator.of(context)
// .pushNamed('/patient-manager/patient',
// arguments: PatientViewArguments(
// widget.signedInUser,
// patientProfile,
// widget.businessUser,
// widget.business,
// "business",
// ));
},
buttonColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"View Medical Records",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
)
],
),
),
),
);
}
Widget displayMyPatientTile(int index, double width) {
var firstName = "";
var lastName = "";
String access = widget.patientAccesses[index].status.toUpperCase();
TextSpan accessWithColour;
var hasAccess = false;
hasAccess = hasAccessToProfile(index);
//print(hasAccess);
if (access == "APPROVED") {
firstName = widget.patientAccesses[index].fname;
lastName = widget.patientAccesses[index].lname;
accessWithColour = TextSpan(
text: "$access\n",
style: TextStyle(
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
} else if (access == "PENDING") {
firstName = "${widget.patientAccesses[index].fname[0]}********";
lastName = "${widget.patientAccesses[index].lname[0]}********";
accessWithColour = TextSpan(
text: "$access\n",
style: TextStyle(
color: MihColors.getGreyColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
} else {
firstName = "${widget.patientAccesses[index].fname[0]}********";
lastName = "${widget.patientAccesses[index].lname[0]}********";
accessWithColour = TextSpan(
text: "$access\n",
style: TextStyle(
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
}
return ListTile(
title: Text(
"$firstName $lastName",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
subtitle: RichText(
text: TextSpan(
text: "ID No.: ${widget.patientAccesses[index].id_no}\n",
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
const TextSpan(text: "Access: "),
accessWithColour,
]),
),
onTap: () async {
Patient? p;
if (hasAccess) {
await MIHApiCalls.fetchPatientByAppId(
widget.patientAccesses[index].app_id)
.then((result) {
setState(() {
p = result;
});
});
patientProfileChoicePopUp(index, p, width);
} else {
noAccessWarning(index);
}
},
trailing: Icon(
Icons.arrow_forward,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
);
}
@override
void dispose() {
dateController.dispose();
timeController.dispose();
idController.dispose();
fnameController.dispose();
lnameController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemCount: widget.patientAccesses.length,
itemBuilder: (context, index) {
return displayMyPatientTile(index, screenWidth);
},
);
}
}

View File

@@ -0,0 +1,15 @@
import 'package:flutter/material.dart';
class BuildWaitingRoomList extends StatefulWidget {
const BuildWaitingRoomList({super.key});
@override
State<BuildWaitingRoomList> createState() => _BuildWaitingRoomListState();
}
class _BuildWaitingRoomListState extends State<BuildWaitingRoomList> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}

View File

@@ -0,0 +1,51 @@
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 PatManagerTile extends StatefulWidget {
final PatManagerArguments arguments;
final double packageSize;
const PatManagerTile({
super.key,
required this.arguments,
required this.packageSize,
});
@override
State<PatManagerTile> createState() => _PatManagerTileState();
}
class _PatManagerTileState extends State<PatManagerTile> {
@override
Widget build(BuildContext context) {
return MihPackageTile(
authenticateUser: true,
onTap: () {
context.goNamed(
'patientManager',
extra: widget.arguments,
);
// Navigator.of(context).pushNamed(
// '/patient-manager',
// arguments: widget.arguments,
// );
},
appName: "Patient Manager",
appIcon: Icon(
MihIcons.patientManager,
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,281 @@
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_service_calls.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_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.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/patient_access.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/list_builders/build_mih_patient_search_list.dart';
import 'package:flutter/material.dart';
class MihPatientSearch extends StatefulWidget {
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final bool personalSelected;
const MihPatientSearch({
super.key,
required this.signedInUser,
required this.business,
required this.businessUser,
required this.personalSelected,
});
@override
State<MihPatientSearch> createState() => _MihPatientSearchState();
}
class _MihPatientSearchState extends State<MihPatientSearch> {
TextEditingController _mihPatientSearchController = TextEditingController();
final FocusNode _focusNode = FocusNode();
final FocusNode _searchFocusNode = FocusNode();
bool hasSearchedBefore = false;
String _mihPatientSearchString = "";
String baseUrl = AppEnviroment.baseApiUrl;
late Future<List<Patient>> _mihPatientSearchResults;
Widget getPatientSearch(double width) {
return MihSingleChildScroll(
child: Column(mainAxisSize: MainAxisSize.max, children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: width / 20),
child: MihSearchBar(
controller: _mihPatientSearchController,
hintText: "Search Patient ID/ Aid No.",
prefixIcon: Icons.search,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onPrefixIconTap: () {
submitPatientSearch();
},
onClearIconTap: () {
setState(() {
_mihPatientSearchController.clear();
_mihPatientSearchString = "";
});
submitPatientSearch();
//To-Do: Implement the search function
// print("To-Do: Implement the search function");
},
searchFocusNode: _searchFocusNode,
),
),
//spacer
const SizedBox(height: 10),
FutureBuilder(
future: _mihPatientSearchResults,
builder: (context, snapshot) {
//print("patient Liust ${snapshot.data}");
if (snapshot.connectionState == ConnectionState.waiting) {
return const Mihloadingcircle();
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
List<Patient> patientsList;
if (_mihPatientSearchString == "") {
patientsList = [];
} else {
patientsList = filterSearchResults(
snapshot.data!, _mihPatientSearchString);
//print(patientsList);
}
return displayPatientList(patientsList, _mihPatientSearchString);
} else {
return Center(
child: Text(
"Error pulling Patients Data\n$baseUrl/patients/search/$_mihPatientSearchString",
style: TextStyle(
fontSize: 25,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")),
textAlign: TextAlign.center,
),
);
}
},
),
]),
);
}
List<Patient> filterSearchResults(List<Patient> patList, String query) {
List<Patient> templist = [];
//print(query);
for (var item in patList) {
if (item.id_no.contains(_mihPatientSearchString) ||
item.medical_aid_no.contains(_mihPatientSearchString)) {
//print(item.medical_aid_no);
templist.add(item);
}
}
return templist;
}
Widget displayPatientList(List<Patient> patientsList, String searchString) {
if (patientsList.isNotEmpty) {
return BuildMihPatientSearchList(
patients: patientsList,
signedInUser: widget.signedInUser,
business: widget.business,
businessUser: widget.businessUser,
personalSelected: widget.personalSelected,
);
} else if (patientsList.isEmpty && searchString != "") {
return Column(
children: [
const SizedBox(height: 50),
Icon(
MihIcons.iDontKnow,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 10),
Text(
"Let's try refining your search",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
],
);
} else {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.patientProfile,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 10),
Text(
"Search for a Patient of Mzansi to add to your Patient List",
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:
"You can search using their ID Number or Medical Aid No."),
// WidgetSpan(
// alignment: PlaceholderAlignment.middle,
// child: Icon(
// Icons.menu,
// size: 20,
// color: MzansiInnovationHub.of(context)!
// .theme
// .secondaryColor(),
// ),
// ),
// TextSpan(text: " to add your first loyalty card"),
],
),
),
),
],
),
);
// return Padding(
// padding: const EdgeInsets.only(top: 35.0),
// child: Center(
// child: Text(
// "Enter ID or Medical Aid No. of Patient",
// style: TextStyle(
// fontSize: 25,
// color:
// MihColors.getGreyColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
// textAlign: TextAlign.center,
// ),
// ),
// );
}
}
void submitPatientSearch() {
if (_mihPatientSearchController.text != "") {
setState(() {
_mihPatientSearchString = _mihPatientSearchController.text;
_mihPatientSearchResults =
MIHApiCalls.fetchPatients(_mihPatientSearchString);
hasSearchedBefore = true;
});
}
}
//Patient Access Widgets/ Functions
List<PatientAccess> filterAccessResults(
List<PatientAccess> patAccList, String query) {
List<PatientAccess> templist = [];
//print(query);
for (var item in patAccList) {
if (item.id_no.contains(query)) {
//print(item.medical_aid_no);
templist.add(item);
}
}
return templist;
}
@override
void initState() {
super.initState();
_mihPatientSearchResults = MIHApiCalls.fetchPatients("abc");
}
@override
void dispose() {
super.dispose();
_searchFocusNode.dispose();
_mihPatientSearchController.dispose();
_focusNode.dispose();
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.sizeOf(context);
final double width = size.width;
return MihPackageToolBody(
borderOn: false,
innerHorizontalPadding: 10,
bodyItem: getPatientSearch(width),
);
}
}

View File

@@ -0,0 +1,265 @@
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_service_calls.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_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.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/patient_access.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/list_builders/build_my_patient_list_list.dart';
import 'package:flutter/material.dart';
class MyPatientList extends StatefulWidget {
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final bool personalSelected;
const MyPatientList({
super.key,
required this.signedInUser,
this.business,
this.businessUser,
this.personalSelected = false,
});
@override
State<MyPatientList> createState() => _MyPatientListState();
}
class _MyPatientListState extends State<MyPatientList> {
late Future<List<PatientAccess>> _myPatientList;
TextEditingController _myPatientSearchController = TextEditingController();
final FocusNode _searchFocusNode = FocusNode();
bool hasSearchedBefore = false;
String _myPatientIdSearchString = "";
String baseUrl = AppEnviroment.baseApiUrl;
final FocusNode _focusNode = FocusNode();
Widget myPatientListTool(double width) {
return MihSingleChildScroll(
child: Column(mainAxisSize: MainAxisSize.max, children: [
Padding(
padding: EdgeInsets.symmetric(horizontal: width / 20),
child: MihSearchBar(
controller: _myPatientSearchController,
hintText: "Search Patient ID",
prefixIcon: Icons.search,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
hintColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onPrefixIconTap: () {
setState(() {
_myPatientIdSearchString = _myPatientSearchController.text;
_myPatientList = MIHApiCalls.getPatientAccessListOfBusiness(
widget.business!.business_id);
});
},
onClearIconTap: () {
setState(() {
_myPatientSearchController.clear();
_myPatientIdSearchString = "";
});
getMyPatientList();
},
searchFocusNode: _searchFocusNode,
),
),
//spacer
const SizedBox(height: 10),
FutureBuilder(
future: _myPatientList,
builder: (context, snapshot) {
//print("patient Liust ${snapshot.data}");
if (snapshot.connectionState == ConnectionState.waiting) {
return const Mihloadingcircle();
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
List<PatientAccess> patientsAccessList;
if (_myPatientIdSearchString == "") {
patientsAccessList = snapshot.data!;
} else {
patientsAccessList = filterAccessResults(
snapshot.data!, _myPatientIdSearchString);
//print(patientsList);
}
return displayMyPatientList(patientsAccessList);
} else {
return Center(
child: Text(
"Error pulling Patient Access Data\n$baseUrl/access-requests/business/patient/${widget.business!.business_id}",
style: TextStyle(
fontSize: 25,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")),
textAlign: TextAlign.center,
),
);
}
},
),
]),
);
}
Widget displayMyPatientList(List<PatientAccess> patientsAccessList) {
if (patientsAccessList.isNotEmpty) {
return BuildMyPatientListList(
patientAccesses: patientsAccessList,
signedInUser: widget.signedInUser,
business: widget.business,
businessUser: widget.businessUser,
);
}
if (hasSearchedBefore && _myPatientIdSearchString.isNotEmpty) {
return Column(
children: [
const SizedBox(height: 50),
Icon(
MihIcons.iDontKnow,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 10),
Text(
"Let's try refining your search",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
],
);
} else {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.patientProfile,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 10),
Text(
"You dont have access to any Patients 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.search,
size: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
TextSpan(
text:
" to use Patient Search to request access to their profile."),
],
),
),
),
],
),
);
}
// return Padding(
// padding: const EdgeInsets.only(top: 35.0),
// child: Center(
// child: Text(
// "No Patients matching search",
// style: TextStyle(
// fontSize: 25,
// color: MihColors.getGreyColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
// textAlign: TextAlign.center,
// ),
// ),
// );
}
List<PatientAccess> filterAccessResults(
List<PatientAccess> patAccList, String query) {
List<PatientAccess> templist = [];
for (var item in patAccList) {
if (item.id_no.contains(query)) {
templist.add(item);
}
}
return templist;
}
void getMyPatientList() {
setState(() {
_myPatientList = MIHApiCalls.getPatientAccessListOfBusiness(
widget.business!.business_id);
hasSearchedBefore = true;
});
}
@override
void initState() {
super.initState();
_myPatientList = MIHApiCalls.getPatientAccessListOfBusiness(
widget.business!.business_id);
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_myPatientSearchController.dispose();
_searchFocusNode.dispose();
_focusNode.dispose();
}
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.sizeOf(context);
final double width = size.width;
return MihPackageToolBody(
borderOn: false,
innerHorizontalPadding: 10,
bodyItem: myPatientListTool(width),
);
}
}

View File

@@ -0,0 +1,623 @@
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_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.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_mzansi_calendar_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_calendar.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_package_components/mih_time_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_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/appointment.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_packages/calendar/builder/build_appointment_list.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class WaitingRoom extends StatefulWidget {
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final bool personalSelected;
final Function(int) onIndexChange;
const WaitingRoom({
super.key,
required this.signedInUser,
required this.business,
required this.businessUser,
required this.personalSelected,
required this.onIndexChange,
});
@override
State<WaitingRoom> createState() => _WaitingRoomState();
}
class _WaitingRoomState extends State<WaitingRoom> {
TextEditingController selectedAppointmentDateController =
TextEditingController();
final TextEditingController _appointmentTitleController =
TextEditingController();
final TextEditingController _appointmentDescriptionIDController =
TextEditingController();
final TextEditingController _appointmentDateController =
TextEditingController();
final TextEditingController _appointmentTimeController =
TextEditingController();
final TextEditingController _patientController = TextEditingController();
String baseUrl = AppEnviroment.baseApiUrl;
late Future<List<Appointment>> businessAppointmentResults;
late Future<List<Appointment>> appointmentResults;
bool inWaitingRoom = true;
bool isLoading = true;
final _formKey = GlobalKey<FormState>();
// Business Appointment Tool
Widget getBusinessAppointmentsTool(double width) {
return Consumer<MihCalendarProvider>(
builder: (BuildContext context, MihCalendarProvider mihCalendarProvider,
Widget? child) {
if (isLoading) {
return const Center(
child: Mihloadingcircle(),
);
}
return Stack(
children: [
MihSingleChildScroll(
child: Column(
children: [
MIHCalendar(
calendarWidth: 500,
rowHeight: 35,
setDate: (value) {
mihCalendarProvider.setSelectedDay(value);
setState(() {
selectedAppointmentDateController.text = value;
});
}),
// Divider(
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
Row(
mainAxisSize: MainAxisSize.max,
children: [
displayAppointmentList(mihCalendarProvider),
],
)
],
),
),
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 Appointment",
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: () {
// addAppointmentWindow();
appointmentTypeSelection(mihCalendarProvider, width);
},
)
],
),
),
],
);
},
);
}
Widget displayAppointmentList(MihCalendarProvider mihCalendarProvider) {
if (mihCalendarProvider.businessAppointments!.isNotEmpty) {
return Expanded(
child: BuildAppointmentList(
inWaitingRoom: true,
titleController: _appointmentTitleController,
descriptionIDController: _appointmentDescriptionIDController,
patientIdController: _patientController,
dateController: _appointmentDateController,
timeController: _appointmentTimeController,
),
);
}
return Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50),
Icon(
MihIcons.calendar,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 10),
Text(
"No Appointments for ${mihCalendarProvider.selectedDay}",
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 an appointment or select a different date"),
],
),
),
),
],
),
),
);
// return Expanded(
// child: Padding(
// padding: const EdgeInsets.only(top: 35.0),
// child: Align(
// alignment: Alignment.center,
// child: Text(
// "No Appointments for $selectedDay",
// style: TextStyle(
// fontSize: 25,
// color: MihColors.getGreyColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// textAlign: TextAlign.center,
// softWrap: true,
// ),
// ),
// ),
// );
}
void appointmentTypeSelection(
MihCalendarProvider mihCalendarProvider, double width) {
String question = "What type of appointment would you like to add?";
question +=
"\n\nExisting Patient: Add an appointment for an patient your practice has access to.";
question +=
"\nExisting MIH User: Add an appointment for an existing MIH user your practice does not have access to.";
question +=
"\nSkeleton Appointment: Add an appointment without a patient linked.";
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return MihPackageWindow(
fullscreen: false,
windowTitle: "Appointment Type",
onWindowTapClose: () {
context.pop();
},
windowBody: Column(
children: [
Text(
question,
style: TextStyle(
fontSize: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
textAlign: TextAlign.left,
),
const SizedBox(height: 15),
MihButton(
onPressed: () {
widget.onIndexChange(1);
context.pop();
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Existing Patient",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 10),
MihButton(
onPressed: () {
widget.onIndexChange(2);
context.pop();
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Existing MIH User",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 10),
MihButton(
onPressed: () {
Navigator.pop(context);
addAppointmentWindow(mihCalendarProvider, width);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
width: 300,
child: Text(
"Skeleton Appointment",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
);
},
);
}
void addAppointmentWindow(
MihCalendarProvider mihCalendarProvider, double width) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return MihPackageWindow(
fullscreen: false,
windowTitle: "Add Appointment",
onWindowTapClose: () {
context.pop();
_appointmentDateController.clear();
_appointmentTimeController.clear();
_appointmentTitleController.clear();
_appointmentDescriptionIDController.clear();
_patientController.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: _appointmentTitleController,
multiLineInput: false,
requiredText: true,
hintText: "Appointment Title",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10),
MihDateField(
controller: _appointmentDateController,
labelText: "Date",
required: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10),
MihTimeField(
controller: _appointmentTimeController,
labelText: "Time",
required: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 10),
MihTextFormField(
height: 250,
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
inputColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
controller: _appointmentDescriptionIDController,
multiLineInput: true,
requiredText: true,
hintText: "Description",
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 20),
Center(
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
addAppointmentCall(mihCalendarProvider);
} 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,
),
),
),
),
],
),
],
),
),
);
},
);
}
Future<void> addAppointmentCall(
MihCalendarProvider mihCalendarProvider) async {
if (isAppointmentInputValid()) {
int statusCode;
if (widget.personalSelected == false) {
statusCode = await MihMzansiCalendarApis.addBusinessAppointment(
widget.signedInUser,
widget.business!,
widget.businessUser!,
true,
_appointmentTitleController.text,
_appointmentDescriptionIDController.text,
_appointmentDateController.text,
_appointmentTimeController.text,
mihCalendarProvider,
context,
);
} else {
statusCode = await MihMzansiCalendarApis.addPersonalAppointment(
widget.signedInUser,
_appointmentTitleController.text,
_appointmentDescriptionIDController.text,
_appointmentDateController.text,
_appointmentTimeController.text,
mihCalendarProvider,
context,
);
}
if (statusCode == 201) {
context.pop();
successPopUp("Successfully Added Appointment",
"You appointment has been successfully added to your calendar.");
_loadInitialAppointments();
} else {
internetConnectionPopUp();
}
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Input Error");
},
);
}
checkforchange();
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(
errorType: "Internet Connection",
);
},
);
}
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();
setState(() {
_appointmentDateController.clear();
_appointmentTimeController.clear();
_appointmentTitleController.clear();
_appointmentDescriptionIDController.clear();
});
},
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"),
);
},
);
}
bool isAppointmentInputValid() {
if (_appointmentDescriptionIDController.text.isEmpty ||
_appointmentDateController.text.isEmpty ||
_appointmentTimeController.text.isEmpty) {
return false;
} else {
return true;
}
}
void checkforchange() {
setState(() {
isLoading = true;
});
_loadInitialAppointments();
}
Future<void> _loadInitialAppointments() async {
MzansiProfileProvider mzansiProfileProvider =
context.read<MzansiProfileProvider>();
MihCalendarProvider mihCalendarProvider =
context.read<MihCalendarProvider>();
await MihMzansiCalendarApis.getBusinessAppointments(
mzansiProfileProvider.business!.business_id,
false,
mihCalendarProvider.selectedDay,
mihCalendarProvider,
);
setState(() {
isLoading = false;
});
}
@override
void dispose() {
selectedAppointmentDateController.dispose();
_appointmentDateController.dispose();
_appointmentTimeController.dispose();
_appointmentTitleController.dispose();
_appointmentDescriptionIDController.dispose();
super.dispose();
}
@override
void initState() {
selectedAppointmentDateController.addListener(checkforchange);
WidgetsBinding.instance.addPostFrameCallback((_) {
_loadInitialAppointments();
});
super.initState();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageToolBody(
borderOn: false,
bodyItem: getBusinessAppointmentsTool(screenWidth),
);
}
}

View File

@@ -0,0 +1,125 @@
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_manager/package_tools/mih_patient_search.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/package_tools/my_patient_list.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/package_tools/waiting_room.dart';
import 'package:flutter/material.dart';
class PatManager extends StatefulWidget {
final PatManagerArguments arguments;
const PatManager({
super.key,
required this.arguments,
});
@override
State<PatManager> createState() => _PatManagerState();
}
class _PatManagerState extends State<PatManager> {
int _selcetedIndex = 0;
void updateIndex(int index) {
setState(() {
_selcetedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return MihPackage(
appActionButton: getActionButton(),
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
},
);
}
MihPackageAction getActionButton() {
return MihPackageAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
// Navigator.of(context).pop();
context.goNamed(
'mihHome',
);
FocusScope.of(context).unfocus();
},
);
}
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.calendar_month)] = () {
setState(() {
_selcetedIndex = 0;
});
};
temp[const Icon(Icons.check_box_outlined)] = () {
setState(() {
_selcetedIndex = 1;
});
};
temp[const Icon(Icons.search)] = () {
setState(() {
_selcetedIndex = 2;
});
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
//appointment here
// Appointments(
// signedInUser: widget.arguments.signedInUser,
// business: widget.arguments.business,
// personalSelected: widget.arguments.personalSelected,
// ),
WaitingRoom(
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
businessUser: widget.arguments.businessUser,
personalSelected: widget.arguments.personalSelected,
onIndexChange: updateIndex,
),
MyPatientList(
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
businessUser: widget.arguments.businessUser,
personalSelected: widget.arguments.personalSelected,
),
MihPatientSearch(
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
personalSelected: widget.arguments.personalSelected,
businessUser: widget.arguments.businessUser,
),
];
return toolBodies;
}
List<String> getToolTitle() {
List<String> toolTitles = [
"Waiting Room",
"My Patients",
"Search Patients",
];
return toolTitles;
}
}

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;
}
}