new Pat manager files

This commit is contained in:
2025-03-04 09:06:16 +02:00
parent 5e11e4522a
commit eff4fae83e
15 changed files with 2253 additions and 168 deletions

View File

@@ -8,15 +8,12 @@ import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_window.dart'
import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih-app_tool_body.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/appointment.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/arguments.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/business.dart';
import 'package:Mzansi_Innovation_Hub/mih_packages/calendar/builder/build_appointment_list.dart';
import 'package:flutter/material.dart';
import '../../main.dart';
import '../../mih_components/mih_calendar.dart';
import '../../mih_components/mih_layout/mih_action.dart';
import '../../mih_components/mih_layout/mih_header.dart';
import '../../mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import '../../mih_env/env.dart';
import '../../mih_objects/app_user.dart';
@@ -38,8 +35,8 @@ class Appointments extends StatefulWidget {
}
class _PatientAccessRequestState extends State<Appointments> {
TextEditingController filterController = TextEditingController();
TextEditingController appointmentDateController = TextEditingController();
TextEditingController selectedAppointmentDateController =
TextEditingController();
final TextEditingController _appointmentTitleController =
TextEditingController();
final TextEditingController _appointmentDescriptionIDController =
@@ -50,12 +47,6 @@ class _PatientAccessRequestState extends State<Appointments> {
TextEditingController();
String baseUrl = AppEnviroment.baseApiUrl;
String errorCode = "";
String errorBody = "";
String datefilter = "";
String accessFilter = "";
bool forceRefresh = false;
late String selectedDropdown;
String selectedDay = DateTime.now().toString().split(" ")[0];
late Future<List<Appointment>> personalAppointmentResults;
@@ -68,8 +59,12 @@ class _PatientAccessRequestState extends State<Appointments> {
child: BuildAppointmentList(
appointmentList: appointmentList,
signedInUser: widget.signedInUser,
business: widget.business,
personalSelected: widget.personalSelected,
inWaitingRoom: false,
titleController: _appointmentTitleController,
descriptionIDController: _appointmentDescriptionIDController,
patientIdController: null,
dateController: _appointmentDateController,
timeController: _appointmentTimeController,
),
@@ -227,6 +222,7 @@ class _PatientAccessRequestState extends State<Appointments> {
if (widget.personalSelected == false) {
appointmentResults = MihMzansiCalendarApis.getBusinessAppointments(
widget.business!.business_id,
false,
selectedDay,
);
} else {
@@ -238,36 +234,6 @@ class _PatientAccessRequestState extends State<Appointments> {
});
}
MIHAction getActionButton() {
return MIHAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).popAndPushNamed(
'/',
arguments: AuthArguments(true, false),
);
},
);
}
MIHHeader getHeader() {
return const MIHHeader(
headerAlignment: MainAxisAlignment.center,
headerItems: [
Text(
"Appointments",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
],
);
}
Widget getBody() {
return Stack(
children: [
@@ -286,7 +252,7 @@ class _PatientAccessRequestState extends State<Appointments> {
setDate: (value) {
setState(() {
selectedDay = value;
appointmentDateController.text = selectedDay;
selectedAppointmentDateController.text = selectedDay;
});
}),
// Divider(
@@ -348,8 +314,7 @@ class _PatientAccessRequestState extends State<Appointments> {
@override
void dispose() {
filterController.dispose();
appointmentDateController.dispose();
selectedAppointmentDateController.dispose();
_appointmentDateController.dispose();
_appointmentTimeController.dispose();
_appointmentTitleController.dispose();
@@ -359,11 +324,12 @@ class _PatientAccessRequestState extends State<Appointments> {
@override
void initState() {
appointmentDateController.addListener(checkforchange);
selectedAppointmentDateController.addListener(checkforchange);
setState(() {
if (widget.personalSelected == false) {
appointmentResults = MihMzansiCalendarApis.getBusinessAppointments(
widget.business!.business_id,
false,
selectedDay,
);
} else {

View File

@@ -11,13 +11,18 @@ import 'package:Mzansi_Innovation_Hub/mih_components/mih_pop_up_messages/mih_err
import 'package:Mzansi_Innovation_Hub/mih_env/env.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/app_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/appointment.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/business.dart';
import 'package:flutter/material.dart';
class BuildAppointmentList extends StatefulWidget {
final List<Appointment> appointmentList;
final AppUser signedInUser;
final Business? business;
final bool personalSelected;
final bool inWaitingRoom;
final TextEditingController titleController;
final TextEditingController descriptionIDController;
final TextEditingController? patientIdController;
final TextEditingController dateController;
final TextEditingController timeController;
@@ -25,8 +30,12 @@ class BuildAppointmentList extends StatefulWidget {
super.key,
required this.appointmentList,
required this.signedInUser,
required this.business,
required this.personalSelected,
required this.inWaitingRoom,
required this.titleController,
required this.descriptionIDController,
required this.patientIdController,
required this.dateController,
required this.timeController,
});
@@ -37,6 +46,7 @@ class BuildAppointmentList extends StatefulWidget {
class _BuildAppointmentListState extends State<BuildAppointmentList> {
String baseAPI = AppEnviroment.baseApiUrl;
TextEditingController patientIdController = TextEditingController();
TextEditingController dateController = TextEditingController();
TextEditingController timeController = TextEditingController();
TextEditingController idController = TextEditingController();
@@ -122,7 +132,11 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
.split('T')[1]
.substring(0, 5);
});
appointmentDetailsWindow(index);
if (widget.inWaitingRoom == false) {
appointmentDetailsWindow(index);
} else {
waitingRiinAppointmentDetailsWindow(index);
}
},
),
),
@@ -233,6 +247,120 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
);
}
void waitingRiinAppointmentDetailsWindow(int index) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return MIHWindow(
fullscreen: false,
windowTitle: "Appointment Details",
windowTools: [
Visibility(
visible: canEditAppointment(index),
child: IconButton(
onPressed: () {
deleteAppointmentConfirmationWindow(index);
},
icon: const Icon(Icons.delete),
),
),
],
onWindowTapClose: () {
Navigator.of(context).pop();
widget.dateController.clear();
widget.timeController.clear();
widget.titleController.clear();
widget.descriptionIDController.clear();
},
windowBody: [
SizedBox(
// width: 500,
child: MIHTextField(
controller: widget.titleController,
hintText: "Title",
editable: false,
required: false,
),
),
const SizedBox(height: 10),
SizedBox(
// width: 500,
child: MIHTextField(
controller: widget.titleController,
hintText: "Patient ID Number",
editable: false,
required: false,
),
),
const SizedBox(height: 10),
SizedBox(
// width: 500,
child: MIHTextField(
controller: widget.dateController,
hintText: "Date",
editable: false,
required: false,
)),
const SizedBox(height: 10),
SizedBox(
// width: 500,
child: MIHTextField(
controller: widget.timeController,
hintText: "Time",
editable: false,
required: false,
)),
const SizedBox(height: 10),
SizedBox(
// width: 500,
height: 250,
child: MIHMLTextField(
controller: widget.descriptionIDController,
hintText: "Description",
editable: false,
required: false,
),
),
const SizedBox(height: 20),
Visibility(
visible: canEditAppointment(index),
child: SizedBox(
width: 500,
height: 50,
child: MIHButton(
onTap: () {
appointmentUpdateWindow(index);
},
buttonText: "Edit",
buttonColor:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
textColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
),
),
),
// SizedBox(
// width: 500,
// height: 50,
// child: MIHButton(
// onTap: () {
// addAppointmentCall();
// checkforchange();
// },
// buttonText: "Add",
// buttonColor:
// MzanziInnovationHub.of(context)!.theme.successColor(),
// textColor:
// MzanziInnovationHub.of(context)!.theme.primaryColor(),
// ),
// ),
],
);
},
);
}
void appointmentUpdateWindow(int index) {
showDialog(
context: context,
@@ -379,6 +507,7 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
if (isAppointmentInputValid()) {
MihMzansiCalendarApis.updatePersonalAppointment(
widget.signedInUser,
widget.business,
widget.appointmentList[index].idappointments,
widget.titleController.text,
widget.descriptionIDController.text,
@@ -405,7 +534,19 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
}
bool canEditAppointment(int index) {
if (widget.appointmentList[index].business_id == "") {
if (widget.personalSelected == true &&
widget.appointmentList[index].app_id == widget.signedInUser.app_id &&
widget.appointmentList[index].business_id == "") {
return true;
} else if (widget.personalSelected == false &&
widget.appointmentList[index].business_id ==
widget.business!.business_id &&
widget.appointmentList[index].app_id.isEmpty) {
return true;
} else if (widget.personalSelected == false &&
widget.appointmentList[index].business_id ==
widget.business!.business_id &&
widget.appointmentList[index].app_id.isNotEmpty) {
return true;
} else {
return false;

View File

@@ -400,10 +400,11 @@ class _MIHHomeState extends State<MIHHome> {
onTap: () {
Navigator.of(context).pushNamed(
'/patient-manager',
arguments: BusinessArguments(
arguments: PatManagerArguments(
widget.signedInUser,
widget.businessUser,
widget.personalSelected,
widget.business,
widget.businessUser,
),
);
},

View File

@@ -135,6 +135,7 @@ class _BuildPatientsListState extends State<BuildPatientAccessList> {
MIHApiCalls.addAppointmentAPICall(
widget.arguments.business!.business_id,
widget.patientAccesses[index].app_id,
false,
dateController.text,
timeController.text,
widget.arguments,

View File

@@ -175,6 +175,7 @@ class _BuildPatientsListState extends State<BuildPatientsList> {
MIHApiCalls.addAppointmentAPICall(
widget.arguments.business!.business_id,
widget.patients[index].app_id,
false,
dateController.text,
timeController.text,
widget.arguments,
@@ -523,14 +524,14 @@ class _BuildPatientsListState extends State<BuildPatientsList> {
MzanziInnovationHub.of(context)!.theme.primaryColor(),
onTap: () {
//print("Send access Request...");
MIHApiCalls.addPatientAccessAPICall(
widget.business!.business_id,
widget.patients[index].app_id,
"patient",
widget.business!.Name,
widget.arguments,
context,
);
// MIHApiCalls.addPatientAccessAPICall(
// widget.business!.business_id,
// widget.patients[index].app_id,
// "patient",
// widget.business!.Name,
// widget.arguments,
// context,
// );
},
),
),
@@ -548,12 +549,12 @@ class _BuildPatientsListState extends State<BuildPatientsList> {
MzanziInnovationHub.of(context)!.theme.primaryColor(),
onTap: () {
print("Send rewaply access Request...");
MIHApiCalls.reapplyPatientAccessAPICall(
widget.business!.business_id,
widget.patients[index].app_id,
widget.arguments,
context,
);
// MIHApiCalls.reapplyPatientAccessAPICall(
// widget.business!.business_id,
// widget.patients[index].app_id,
// widget.arguments,
// context,
// );
},
),
),

View File

@@ -475,6 +475,7 @@ class _BuildPatientsListState extends State<BuildPatientQueueList> {
MIHApiCalls.deleteApointmentAPICall(
widget.patientQueue[index].idpatient_queue,
widget.patientQueue[index].app_id,
false,
widget.patientQueue[index].date_time,
BusinessArguments(
widget.signedInUser,
@@ -500,6 +501,7 @@ class _BuildPatientsListState extends State<BuildPatientQueueList> {
MIHApiCalls.updateApointmentAPICall(
widget.patientQueue[index].idpatient_queue,
widget.patientQueue[index].app_id,
false,
widget.business!.Name,
widget.patientQueue[index].date_time,
dateController.text,

View File

@@ -0,0 +1,223 @@
import 'package:Mzansi_Innovation_Hub/main.dart';
import 'package:Mzansi_Innovation_Hub/mih_apis/mih_api_calls.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_search_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih-app_tool_body.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:Mzansi_Innovation_Hub/mih_env/env.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/app_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/business.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/business_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/patient_access.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/patients.dart';
import 'package:Mzansi_Innovation_Hub/mih_packages/patient_profile/pat_manager/list_builders/build_mih_patient_search_list.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.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();
String _mihPatientSearchString = "";
String baseUrl = AppEnviroment.baseApiUrl;
late Future<List<Patient>> _mihPatientSearchResults;
Widget getPatientSearch() {
return KeyboardListener(
focusNode: _focusNode,
autofocus: true,
onKeyEvent: (event) async {
if (event is KeyDownEvent &&
event.logicalKey == LogicalKeyboardKey.enter) {
// submitPatientForm();
submitPatientSearch();
//To-Do: Implement the search function
// print("To-Do: Implement the search function");
}
},
child: Column(mainAxisSize: MainAxisSize.max, children: [
const Text(
"MIH Patient Lookup",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
Divider(color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
//spacer
const SizedBox(height: 10),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
flex: 1,
child: MIHSearchField(
controller: _mihPatientSearchController,
hintText: "ID or Medical Aid No. Search",
required: false,
editable: true,
onTap: () {
// submitPatientForm();
submitPatientSearch();
//To-Do: Implement the search function
// print("To-Do: Implement the search function");
},
),
),
IconButton(
onPressed: () {
setState(() {
_mihPatientSearchController.clear();
_mihPatientSearchString = "";
});
submitPatientSearch();
//To-Do: Implement the search function
// print("To-Do: Implement the search function");
},
icon: const Icon(
Icons.filter_alt_off,
size: 25,
))
],
),
//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:
MzanziInnovationHub.of(context)!.theme.errorColor()),
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 Padding(
padding: const EdgeInsets.only(top: 35.0),
child: Center(
child: Text(
"No ID or Medical Aid No. matches a Patient",
style: TextStyle(
fontSize: 25,
color:
MzanziInnovationHub.of(context)!.theme.messageTextColor()),
textAlign: TextAlign.center,
),
),
);
} else {
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:
MzanziInnovationHub.of(context)!.theme.messageTextColor()),
textAlign: TextAlign.center,
),
),
);
}
}
void submitPatientSearch() {
if (_mihPatientSearchController.text != "") {
setState(() {
_mihPatientSearchString = _mihPatientSearchController.text;
_mihPatientSearchResults =
MIHApiCalls.fetchPatients(_mihPatientSearchString);
});
}
}
//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
Widget build(BuildContext context) {
return MihAppToolBody(
borderOn: true,
bodyItem: getPatientSearch(),
);
}
}

View File

@@ -0,0 +1,202 @@
import 'package:Mzansi_Innovation_Hub/main.dart';
import 'package:Mzansi_Innovation_Hub/mih_apis/mih_api_calls.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_search_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih-app_tool_body.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:Mzansi_Innovation_Hub/mih_env/env.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/app_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/business.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/business_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/patient_access.dart';
import 'package:Mzansi_Innovation_Hub/mih_packages/patient_profile/pat_manager/list_builders/build_my_patient_list_list.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.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();
String _myPatientIdSearchString = "";
String baseUrl = AppEnviroment.baseApiUrl;
final FocusNode _focusNode = FocusNode();
Widget myPatientListTool() {
return KeyboardListener(
focusNode: _focusNode,
autofocus: true,
onKeyEvent: (event) async {
if (event is KeyDownEvent &&
event.logicalKey == LogicalKeyboardKey.enter) {
setState(() {
_myPatientIdSearchString = _myPatientSearchController.text;
_myPatientList = MIHApiCalls.getPatientAccessListOfBusiness(
widget.business!.business_id);
});
}
},
child: Column(mainAxisSize: MainAxisSize.max, children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"My Patient List",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
IconButton(
iconSize: 20,
icon: const Icon(
Icons.refresh,
),
onPressed: () {
getMyPatientList();
},
),
],
),
Divider(color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
//spacer
const SizedBox(height: 10),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Flexible(
flex: 1,
child: MIHSearchField(
controller: _myPatientSearchController,
hintText: "Patient ID Search",
required: false,
editable: true,
onTap: () {
setState(() {
_myPatientIdSearchString = _myPatientSearchController.text;
_myPatientList = MIHApiCalls.getPatientAccessListOfBusiness(
widget.business!.business_id);
});
},
),
),
IconButton(
onPressed: () {
setState(() {
_myPatientSearchController.clear();
_myPatientIdSearchString = "";
});
getMyPatientList();
},
icon: const Icon(
Icons.filter_alt_off,
size: 25,
))
],
),
//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:
MzanziInnovationHub.of(context)!.theme.errorColor()),
textAlign: TextAlign.center,
),
);
}
},
),
]),
);
}
Widget displayMyPatientList(List<PatientAccess> patientsAccessList) {
if (patientsAccessList.isNotEmpty) {
return BuildMyPatientListList(
patientAccesses: patientsAccessList,
signedInUser: widget.signedInUser,
business: widget.business,
businessUser: widget.businessUser,
);
}
return Padding(
padding: const EdgeInsets.only(top: 35.0),
child: Center(
child: Text(
"No Patients matching search",
style: TextStyle(
fontSize: 25,
color: MzanziInnovationHub.of(context)!.theme.messageTextColor()),
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);
});
}
@override
void initState() {
super.initState();
_myPatientList = MIHApiCalls.getPatientAccessListOfBusiness(
widget.business!.business_id);
}
@override
Widget build(BuildContext context) {
return MihAppToolBody(
borderOn: true,
bodyItem: myPatientListTool(),
);
}
}

View File

@@ -0,0 +1,348 @@
import 'package:Mzansi_Innovation_Hub/main.dart';
import 'package:Mzansi_Innovation_Hub/mih_apis/mih_mzansi_calendar_apis.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_calendar.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_button.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_date_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_multiline_text_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_search_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_text_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_time_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_window.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih-app_tool_body.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_env/env.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/app_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/appointment.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/business.dart';
import 'package:Mzansi_Innovation_Hub/mih_packages/calendar/builder/build_appointment_list.dart';
import 'package:flutter/material.dart';
class WaitingRoom extends StatefulWidget {
final AppUser signedInUser;
final Business? business;
final bool personalSelected;
const WaitingRoom({
super.key,
required this.signedInUser,
this.business,
required this.personalSelected,
});
@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;
String selectedDay = DateTime.now().toString().split(" ")[0];
late Future<List<Appointment>> businessAppointmentResults;
late Future<List<Appointment>> appointmentResults;
// Business Appointment Tool
Widget getBusinessAppointmentsTool() {
return Stack(
children: [
Column(
children: [
const Text(
"Waiting Room",
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
MIHCalendar(
calendarWidth: 500,
rowHeight: 35,
setDate: (value) {
setState(() {
selectedDay = value;
selectedAppointmentDateController.text = selectedDay;
});
}),
// Divider(
// color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
// ),
Row(
mainAxisSize: MainAxisSize.max,
children: [
FutureBuilder(
future: appointmentResults,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Expanded(
child: Center(child: Mihloadingcircle()));
} else if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
return
// Container(child: const Placeholder());
displayAppointmentList(snapshot.requireData);
} else {
return Center(
child: Text(
"Error pulling appointments",
style: TextStyle(
fontSize: 25,
color: MzanziInnovationHub.of(context)!
.theme
.errorColor()),
textAlign: TextAlign.center,
),
);
}
}),
],
)
],
),
Positioned(
right: 0,
bottom: 0,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
child: IconButton(
color: MzanziInnovationHub.of(context)!.theme.primaryColor(),
onPressed: () {
addAppointmentWindow();
},
icon: const Icon(
Icons.add,
size: 50,
),
),
))
],
);
}
Widget displayAppointmentList(List<Appointment> appointmentList) {
if (appointmentList.isNotEmpty) {
return Expanded(
child: BuildAppointmentList(
appointmentList: appointmentList,
signedInUser: widget.signedInUser,
business: widget.business,
personalSelected: widget.personalSelected,
inWaitingRoom: true,
titleController: _appointmentTitleController,
descriptionIDController: _appointmentDescriptionIDController,
patientIdController: _patientController,
dateController: _appointmentDateController,
timeController: _appointmentTimeController,
),
);
}
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: MzanziInnovationHub.of(context)!.theme.messageTextColor(),
),
textAlign: TextAlign.center,
softWrap: true,
),
),
),
);
}
void addAppointmentWindow() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) {
return MIHWindow(
fullscreen: false,
windowTitle: "Add Appointment",
windowTools: [],
onWindowTapClose: () {
Navigator.of(context).pop();
_appointmentDateController.clear();
_appointmentTimeController.clear();
_appointmentTitleController.clear();
_appointmentDescriptionIDController.clear();
_patientController.clear();
},
windowBody: [
SizedBox(
// width: 500,
child: MIHTextField(
controller: _appointmentTitleController,
hintText: "Title",
editable: true,
required: true,
),
),
const SizedBox(height: 10),
SizedBox(
child: MIHSearchField(
controller: _patientController,
hintText: "Patient ID Number",
required: false,
editable: true,
onTap: () {
//To-Do: Add search functionality
},
),
),
const SizedBox(height: 10),
SizedBox(
// width: 500,
child: MIHDateField(
controller: _appointmentDateController,
lableText: "Date",
required: true,
),
),
const SizedBox(height: 10),
SizedBox(
// width: 500,
child: MIHTimeField(
controller: _appointmentTimeController,
lableText: "Time",
required: true,
),
),
const SizedBox(height: 10),
SizedBox(
// width: 500,
height: 250,
child: MIHMLTextField(
controller: _appointmentDescriptionIDController,
hintText: "Description",
editable: true,
required: true,
),
),
const SizedBox(height: 20),
SizedBox(
width: 500,
height: 50,
child: MIHButton(
onTap: () {
//To-Do: Add appointment
print("To-Do: Add appointment");
// addAppointmentCall();
},
buttonText: "Add",
buttonColor:
MzanziInnovationHub.of(context)!.theme.successColor(),
textColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
),
),
],
);
},
);
}
void addAppointmentCall() {
if (isAppointmentInputValid()) {
if (widget.personalSelected == false) {
MihMzansiCalendarApis.addBusinessAppointment(
widget.signedInUser,
widget.business!,
_appointmentTitleController.text,
_appointmentDescriptionIDController.text,
_appointmentDateController.text,
_appointmentTimeController.text,
context,
);
} else {
MihMzansiCalendarApis.addPersonalAppointment(
widget.signedInUser,
_appointmentTitleController.text,
_appointmentDescriptionIDController.text,
_appointmentDateController.text,
_appointmentTimeController.text,
context,
);
}
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Input Error");
},
);
}
checkforchange();
}
bool isAppointmentInputValid() {
if (_appointmentTitleController.text.isEmpty ||
_appointmentDescriptionIDController.text.isEmpty ||
_appointmentDateController.text.isEmpty ||
_appointmentTimeController.text.isEmpty) {
return false;
} else {
return true;
}
}
void checkforchange() {
setState(() {
appointmentResults = MihMzansiCalendarApis.getBusinessAppointments(
widget.business!.business_id,
true,
selectedDay,
);
});
}
@override
void dispose() {
selectedAppointmentDateController.dispose();
_appointmentDateController.dispose();
_appointmentTimeController.dispose();
_appointmentTitleController.dispose();
_appointmentDescriptionIDController.dispose();
super.dispose();
}
@override
void initState() {
selectedAppointmentDateController.addListener(checkforchange);
setState(() {
appointmentResults = MihMzansiCalendarApis.getBusinessAppointments(
widget.business!.business_id,
true,
selectedDay,
);
});
super.initState();
}
@override
Widget build(BuildContext context) {
return MihAppToolBody(
borderOn: true,
bodyItem: getBusinessAppointmentsTool(),
);
}
}

View File

@@ -0,0 +1,665 @@
import 'dart:convert';
import 'package:Mzansi_Innovation_Hub/main.dart';
import 'package:Mzansi_Innovation_Hub/mih_apis/mih_api_calls.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_button.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_date_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_text_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_time_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_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_success_message.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_pop_up_messages/mih_warning_message.dart';
import 'package:Mzansi_Innovation_Hub/mih_env/env.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/app_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/arguments.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/business.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/business_user.dart';
import 'package:Mzansi_Innovation_Hub/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": "/access-review",
}),
);
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 submitApointment(int index) {
//To-Do: Implement the appointment submission
print("To-do: Implement the appointment submission");
// MIHApiCalls.addAppointmentAPICall(
// widget.business!.business_id,
// widget.patients[index].app_id,
// dateController.text,
// timeController.text,
// widget.arguments,
// context,
// );
}
bool isAppointmentFieldsFilled() {
if (dateController.text.isEmpty || timeController.text.isEmpty) {
return false;
} else {
return true;
}
}
void appointmentPopUp(int index) {
var firstLetterFName = widget.patients[index].first_name[0];
var firstLetterLName = widget.patients[index].last_name[0];
var fnameStar = '*' * 8;
var lnameStar = '*' * 8;
setState(() {
idController.text = widget.patients[index].id_no;
fnameController.text = firstLetterFName + fnameStar;
lnameController.text = firstLetterLName + lnameStar;
});
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MIHWindow(
fullscreen: false,
windowTitle: "Patient Appointment",
windowTools: const [],
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: [
MIHTextField(
controller: idController,
hintText: "ID No.",
editable: false,
required: true,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: fnameController,
hintText: "First Name",
editable: false,
required: true,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: lnameController,
hintText: "Surname",
editable: false,
required: true,
),
const SizedBox(height: 10.0),
MIHDateField(
controller: dateController,
lableText: "Date",
required: true,
),
const SizedBox(height: 10.0),
MIHTimeField(
controller: timeController,
lableText: "Time",
required: true,
),
const SizedBox(height: 30.0),
SizedBox(
width: 300,
height: 50,
child: MIHButton(
buttonText: "Book",
buttonColor:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
textColor: MzanziInnovationHub.of(context)!.theme.primaryColor(),
onTap: () {
//print("here1");
bool filled = isAppointmentFieldsFilled();
//print("fields filled: $filled");
if (filled) {
//print("here2");
submitApointment(index);
//print("here3");
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Input Error");
},
);
}
},
),
)
],
),
);
}
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;
});
});
// print(accessStatus);
// print(hasAccess);
var firstLetterFName = widget.patients[index].first_name[0];
var firstLetterLName = widget.patients[index].last_name[0];
var fnameStar = '*' * 8;
var lnameStar = '*' * 8;
if (accessStatus == "") {
accessStatus = "No Access";
}
setState(() {
idController.text = widget.patients[index].id_no;
fnameController.text = firstLetterFName + fnameStar;
lnameController.text = firstLetterLName + lnameStar;
accessStatusController.text = accessStatus.toUpperCase();
});
//print(accessStatus);
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MIHWindow(
fullscreen: false,
windowTitle: "Patient Profile",
windowTools: const [],
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: [
MIHTextField(
controller: idController,
hintText: "ID No.",
editable: false,
required: true,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: fnameController,
hintText: "First Name",
editable: false,
required: true,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: lnameController,
hintText: "Surname",
editable: false,
required: true,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: accessStatusController,
hintText: "Access Status",
editable: false,
required: true,
),
const SizedBox(height: 20.0),
Visibility(
visible: !hasAccess,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
"Important Notice: Requesting Patient Profile Access",
style: TextStyle(
fontWeight: FontWeight.bold,
color: MzanziInnovationHub.of(context)!.theme.errorColor(),
),
),
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: MzanziInnovationHub.of(context)!.theme.errorColor(),
),
),
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:
MzanziInnovationHub.of(context)!.theme.errorColor(),
),
),
),
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:
MzanziInnovationHub.of(context)!.theme.errorColor(),
),
),
),
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:
MzanziInnovationHub.of(context)!.theme.errorColor(),
),
),
),
Text(
"By pressing the \"Request Access\" button you accept the above terms.",
style: TextStyle(
fontWeight: FontWeight.bold,
color: MzanziInnovationHub.of(context)!.theme.errorColor(),
),
),
],
),
),
const SizedBox(height: 20.0),
Wrap(runSpacing: 10, spacing: 10, children: [
Visibility(
visible: hasAccess,
child: SizedBox(
width: 300,
height: 50,
child: MIHButton(
buttonText: "Book Appointment",
buttonColor:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
textColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
onTap: () {
if (hasAccess) {
appointmentPopUp(index);
} else {
noAccessWarning();
}
},
),
),
),
Visibility(
visible: hasAccess,
child: SizedBox(
width: 300,
height: 50,
child: MIHButton(
buttonText: "View Patient Profile",
buttonColor:
MzanziInnovationHub.of(context)!.theme.successColor(),
textColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
onTap: () {
if (hasAccess) {
Navigator.of(context)
.pushNamed('/patient-manager/patient',
arguments: PatientViewArguments(
widget.signedInUser,
widget.patients[index],
widget.businessUser,
widget.business,
"business",
));
} else {
noAccessWarning();
}
},
),
),
),
Visibility(
visible: !hasAccess && accessStatus == "No Access",
child: SizedBox(
width: 300,
height: 50,
child: MIHButton(
buttonText: "Request Access",
buttonColor:
MzanziInnovationHub.of(context)!.theme.successColor(),
textColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
onTap: () {
//print("Send access Request...");
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,
);
},
),
),
),
Visibility(
visible: !hasAccess && accessStatus == "declined",
child: SizedBox(
width: 300,
height: 50,
child: MIHButton(
buttonText: "Re-apply",
buttonColor:
MzanziInnovationHub.of(context)!.theme.successColor(),
textColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
onTap: () {
// print("Send rewaply access Request...");
MIHApiCalls.reapplyPatientAccessAPICall(
widget.business!.business_id,
widget.patients[index].app_id,
widget.personalSelected,
BusinessArguments(
widget.signedInUser,
widget.businessUser,
widget.business,
),
context,
);
},
),
),
),
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",
style: TextStyle(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
),
const SizedBox(
width: 10,
),
Icon(
Icons.star_border_rounded,
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
],
);
} else {
return Text(
"$firstLetterFName$fnameStar $firstLetterLName$lnameStar",
style: TextStyle(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
);
}
}
Widget hasMedicalAid(int index) {
var medAidNoStar = '*' * 8;
if (widget.patients[index].medical_aid == "Yes") {
return ListTile(
title: isMainMember(index),
subtitle: Text(
"ID No.: ${widget.patients[index].id_no}\nMedical Aid No.: $medAidNoStar",
style: TextStyle(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
),
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: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
);
} else {
return ListTile(
title: isMainMember(index),
subtitle: Text(
"ID No.: ${widget.patients[index].id_no}\nMedical Aid No.: $medAidNoStar",
style: TextStyle(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
),
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: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
);
}
}
@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: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
);
},
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,385 @@
import 'package:Mzansi_Innovation_Hub/main.dart';
import 'package:Mzansi_Innovation_Hub/mih_apis/mih_api_calls.dart';
import 'package:Mzansi_Innovation_Hub/mih_apis/mih_mzansi_calendar_apis.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_button.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_date_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_text_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_time_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_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_warning_message.dart';
import 'package:Mzansi_Innovation_Hub/mih_env/env.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/app_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/arguments.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/business.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/business_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/patient_access.dart';
import 'package:Mzansi_Innovation_Hub/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 baseAPI = AppEnviroment.baseApiUrl;
void submitApointment(int index) {
//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}";
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,
);
// MIHApiCalls.addAppointmentAPICall(
// widget.business!.business_id,
// widget.patientAccesses[index].app_id,
// dateController.text,
// timeController.text,
// BusinessArguments(
// widget.signedInUser,
// widget.businessUser,
// widget.business,
// ),
// context,
// );
}
bool isAppointmentFieldsFilled() {
if (dateController.text.isEmpty || timeController.text.isEmpty) {
return false;
} else {
return true;
}
}
void appointmentPopUp(int index) {
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) => MIHWindow(
fullscreen: false,
windowTitle: "Patient Appointment",
windowTools: const [],
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: [
MIHTextField(
controller: idController,
hintText: "ID No.",
editable: false,
required: true,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: fnameController,
hintText: "First Name",
editable: false,
required: true,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: lnameController,
hintText: "Surname",
editable: false,
required: true,
),
const SizedBox(height: 10.0),
MIHDateField(
controller: dateController,
lableText: "Date",
required: true,
),
const SizedBox(height: 10.0),
MIHTimeField(
controller: timeController,
lableText: "Time",
required: true,
),
const SizedBox(height: 30.0),
SizedBox(
width: 300,
height: 50,
child: MIHButton(
buttonText: "Book",
buttonColor:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
textColor: MzanziInnovationHub.of(context)!.theme.primaryColor(),
onTap: () {
//print("here1");
bool filled = isAppointmentFieldsFilled();
//print("fields filled: $filled");
if (filled) {
//print("here2");
submitApointment(index);
//print("here3");
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Input Error");
},
);
}
},
),
)
],
),
);
}
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) 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) => MIHWindow(
fullscreen: false,
windowTitle: "Patient Profile",
windowTools: const [],
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: [
MIHTextField(
controller: idController,
hintText: "ID No.",
editable: false,
required: true,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: fnameController,
hintText: "First Name",
editable: false,
required: true,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: lnameController,
hintText: "Surname",
editable: false,
required: true,
),
const SizedBox(height: 30.0),
Wrap(runSpacing: 10, spacing: 10, children: [
SizedBox(
width: 300,
height: 50,
child: MIHButton(
buttonText: "Book Appointment",
buttonColor:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
textColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
onTap: () {
appointmentPopUp(index);
},
),
),
SizedBox(
width: 300,
height: 50,
child: MIHButton(
buttonText: "View Patient Profile",
buttonColor:
MzanziInnovationHub.of(context)!.theme.successColor(),
textColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
onTap: () {
// Navigator.of(context).pop();
Navigator.of(context).pushNamed('/patient-manager/patient',
arguments: PatientViewArguments(
widget.signedInUser,
patientProfile,
widget.businessUser,
widget.business,
"business",
));
},
),
),
])
],
),
);
}
Widget displayMyPatientTile(int index) {
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: MzanziInnovationHub.of(context)!.theme.successColor()));
} else if (access == "PENDING") {
firstName = "${widget.patientAccesses[index].fname[0]}********";
lastName = "${widget.patientAccesses[index].lname[0]}********";
accessWithColour = TextSpan(
text: "$access\n",
style: TextStyle(
color:
MzanziInnovationHub.of(context)!.theme.messageTextColor()));
} else {
firstName = "${widget.patientAccesses[index].fname[0]}********";
lastName = "${widget.patientAccesses[index].lname[0]}********";
accessWithColour = TextSpan(
text: "$access\n",
style: TextStyle(
color: MzanziInnovationHub.of(context)!.theme.errorColor()));
}
return ListTile(
title: Text(
"$firstName $lastName",
style: TextStyle(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
),
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);
} else {
noAccessWarning(index);
}
},
trailing: Icon(
Icons.arrow_forward,
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
);
}
@override
void dispose() {
dateController.dispose();
timeController.dispose();
idController.dispose();
fnameController.dispose();
lnameController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
);
},
itemCount: widget.patientAccesses.length,
itemBuilder: (context, index) {
return displayMyPatientTile(index);
},
);
}
}

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,101 @@
import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih_app.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih_app_action.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih_app_tools.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/arguments.dart';
import 'package:Mzansi_Innovation_Hub/mih_packages/patient_profile/pat_manager/app_tools/mih_patient_search.dart';
import 'package:Mzansi_Innovation_Hub/mih_packages/patient_profile/pat_manager/app_tools/my_patient_list.dart';
import 'package:Mzansi_Innovation_Hub/mih_packages/patient_profile/pat_manager/app_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;
@override
Widget build(BuildContext context) {
return MihApp(
appActionButton: getActionButton(),
appTools: getTools(),
appBody: getToolBody(),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
print("Index: $_selcetedIndex");
},
);
}
MihAppAction getActionButton() {
return MihAppAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
Navigator.of(context).pop();
},
);
}
MihAppTools 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 MihAppTools(
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,
personalSelected: widget.arguments.personalSelected,
),
MyPatientList(
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
personalSelected: widget.arguments.personalSelected,
),
MihPatientSearch(
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
personalSelected: widget.arguments.personalSelected,
businessUser: widget.arguments.businessUser,
),
];
return toolBodies;
}
}

View File

@@ -73,11 +73,13 @@ class _PatientManagerState extends State<PatientManager> {
Widget displayQueueList(List<PatientQueue> patientQueueList) {
if (patientQueueList.isNotEmpty) {
return BuildPatientQueueList(
patientQueue: patientQueueList,
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
businessUser: widget.arguments.businessUser,
return Expanded(
child: BuildPatientQueueList(
patientQueue: patientQueueList,
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
businessUser: widget.arguments.businessUser,
),
);
}
return Padding(
@@ -95,67 +97,105 @@ class _PatientManagerState extends State<PatientManager> {
}
Widget patientQueue() {
return Column(mainAxisSize: MainAxisSize.max, children: [
//const SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.center,
return Container(
child: Stack(
children: [
const Text(
"Waiting Room",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
IconButton(
iconSize: 20,
icon: const Icon(
Icons.refresh,
),
onPressed: () {
refreshQueue();
},
Column(
mainAxisSize: MainAxisSize.max,
children: [
//const SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"Waiting Room",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
IconButton(
iconSize: 20,
icon: const Icon(
Icons.refresh,
),
onPressed: () {
refreshQueue();
},
),
],
),
// Divider(
// color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
MIHCalendar(
calendarWidth: 500,
rowHeight: 35,
setDate: (value) {
setState(() {
queueDateController.text = value;
});
}),
//spacer
Row(
mainAxisSize: MainAxisSize.max,
children: [
FutureBuilder(
future: patientQueueResults,
builder: (context, snapshot) {
//print("patient Queue List ${snapshot.hasData}");
if (snapshot.connectionState == ConnectionState.waiting) {
return const Mihloadingcircle();
} else if (snapshot.connectionState ==
ConnectionState.done) {
List<PatientQueue> patientQueueList;
// if (searchString == "") {
// patientQueueList = [];
// } else {
patientQueueList = filterQueueResults(
snapshot.requireData, queueDateController.text);
// print(patientQueueList);
// }
return displayQueueList(patientQueueList);
} else {
return Center(
child: Text(
"Error pulling Patients Data\n$baseUrl/patients/search/$searchString",
style: TextStyle(
fontSize: 25,
color: MzanziInnovationHub.of(context)!
.theme
.errorColor()),
textAlign: TextAlign.center,
),
);
}
},
),
],
),
],
),
Positioned(
right: 0,
bottom: 0,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
color:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
child: IconButton(
color: MzanziInnovationHub.of(context)!.theme.primaryColor(),
onPressed: () {
// addAppointmentWindow();
},
icon: const Icon(
Icons.add,
size: 50,
),
),
))
],
),
Divider(color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
MIHCalendar(
calendarWidth: 500,
rowHeight: 35,
setDate: (value) {
setState(() {
queueDateController.text = value;
});
}),
//spacer
FutureBuilder(
future: patientQueueResults,
builder: (context, snapshot) {
//print("patient Queue List ${snapshot.hasData}");
if (snapshot.connectionState == ConnectionState.waiting) {
return const Mihloadingcircle();
} else if (snapshot.connectionState == ConnectionState.done) {
List<PatientQueue> patientQueueList;
// if (searchString == "") {
// patientQueueList = [];
// } else {
patientQueueList = filterQueueResults(
snapshot.requireData, queueDateController.text);
// print(patientQueueList);
// }
return displayQueueList(patientQueueList);
} else {
return Center(
child: Text(
"Error pulling Patients Data\n$baseUrl/patients/search/$searchString",
style: TextStyle(
fontSize: 25,
color: MzanziInnovationHub.of(context)!.theme.errorColor()),
textAlign: TextAlign.center,
),
);
}
},
),
]);
);
}
void refreshQueue() {
@@ -259,7 +299,6 @@ class _PatientManagerState extends State<PatientManager> {
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
Divider(color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
//spacer
const SizedBox(height: 10),
Row(
@@ -309,7 +348,6 @@ class _PatientManagerState extends State<PatientManager> {
filterSearchResults(snapshot.data!, searchString);
//print(patientsList);
}
return displayPatientList(patientsList, searchString);
} else {
return Center(
@@ -347,7 +385,6 @@ class _PatientManagerState extends State<PatientManager> {
}
//Patient Access Widgets/ Functions
List<PatientAccess> filterAccessResults(
List<PatientAccess> patAccList, String query) {
List<PatientAccess> templist = [];
@@ -414,7 +451,6 @@ class _PatientManagerState extends State<PatientManager> {
],
),
Divider(color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
//spacer
const SizedBox(height: 10),
Row(
@@ -446,7 +482,6 @@ class _PatientManagerState extends State<PatientManager> {
))
],
),
//spacer
const SizedBox(height: 10),
FutureBuilder(
@@ -465,7 +500,6 @@ class _PatientManagerState extends State<PatientManager> {
filterAccessResults(snapshot.data!, accessSearchString);
//print(patientsList);
}
return displayPatientAccessList(patientsAccessList);
} else {
return Center(

View File

@@ -45,10 +45,10 @@ packages:
dependency: transitive
description:
name: async
sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
url: "https://pub.dev"
source: hosted
version: "2.11.0"
version: "2.12.0"
barcode:
dependency: transitive
description:
@@ -85,10 +85,10 @@ packages:
dependency: transitive
description:
name: boolean_selector
sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.dev"
source: hosted
version: "2.1.1"
version: "2.1.2"
buffer:
dependency: transitive
description:
@@ -181,10 +181,10 @@ packages:
dependency: transitive
description:
name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev"
source: hosted
version: "1.3.0"
version: "1.4.0"
charcode:
dependency: transitive
description:
@@ -213,10 +213,10 @@ packages:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.dev"
source: hosted
version: "1.1.1"
version: "1.1.2"
code_builder:
dependency: transitive
description:
@@ -229,10 +229,10 @@ packages:
dependency: transitive
description:
name: collection
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
version: "1.19.0"
version: "1.19.1"
convert:
dependency: transitive
description:
@@ -333,10 +333,10 @@ packages:
dependency: transitive
description:
name: fake_async
sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
url: "https://pub.dev"
source: hosted
version: "1.3.1"
version: "1.3.2"
fetch_api:
dependency: transitive
description:
@@ -676,18 +676,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
url: "https://pub.dev"
source: hosted
version: "10.0.7"
version: "10.0.8"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
url: "https://pub.dev"
source: hosted
version: "3.0.8"
version: "3.0.9"
leak_tracker_testing:
dependency: transitive
description:
@@ -764,10 +764,10 @@ packages:
dependency: transitive
description:
name: matcher
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev"
source: hosted
version: "0.12.16+1"
version: "0.12.17"
material_color_utilities:
dependency: transitive
description:
@@ -788,10 +788,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev"
source: hosted
version: "1.15.0"
version: "1.16.0"
mime:
dependency: transitive
description:
@@ -852,10 +852,10 @@ packages:
dependency: transitive
description:
name: path
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
version: "1.9.0"
version: "1.9.1"
path_parsing:
dependency: transitive
description:
@@ -1153,10 +1153,10 @@ packages:
dependency: transitive
description:
name: source_span
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
url: "https://pub.dev"
source: hosted
version: "1.10.0"
version: "1.10.1"
sprintf:
dependency: transitive
description:
@@ -1169,18 +1169,18 @@ packages:
dependency: transitive
description:
name: stack_trace
sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.dev"
source: hosted
version: "1.12.0"
version: "1.12.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
version: "2.1.4"
stream_transform:
dependency: transitive
description:
@@ -1193,10 +1193,10 @@ packages:
dependency: transitive
description:
name: string_scanner
sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.dev"
source: hosted
version: "1.3.0"
version: "1.4.1"
supertokens_flutter:
dependency: "direct main"
description:
@@ -1281,18 +1281,18 @@ packages:
dependency: transitive
description:
name: term_glyph
sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
version: "1.2.2"
test_api:
dependency: transitive
description:
name: test_api
sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
url: "https://pub.dev"
source: hosted
version: "0.7.3"
version: "0.7.4"
timing:
dependency: transitive
description:
@@ -1425,10 +1425,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
url: "https://pub.dev"
source: hosted
version: "14.3.0"
version: "14.3.1"
watcher:
dependency: transitive
description:
@@ -1558,5 +1558,5 @@ packages:
source: hosted
version: "3.1.1"
sdks:
dart: ">=3.6.0 <3.9.0"
dart: ">=3.7.0-0 <3.9.0"
flutter: ">=3.27.0"