From cb25b932ba0f68aac5444eacde68603664e0446a Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Fri, 31 Oct 2025 11:55:49 +0200 Subject: [PATCH] NEW: Patient Manager Provider Setup pt4 --- .../patient_manager_provider.dart | 6 + .../package_tools/mih_business_home.dart | 3 - .../mih_business_user_search.dart | 2 +- .../build_mih_patient_search_list.dart | 303 ++++++++---------- .../package_tools/mih_patient_search.dart | 164 +++------- .../pat_manager/pat_manager.dart | 24 +- .../mih_access_controls_services.dart | 95 ++++++ .../mih_services/mih_patient_services.dart | 20 +- .../lib/mih_services/mih_service_calls.dart | 4 +- 9 files changed, 306 insertions(+), 315 deletions(-) diff --git a/Frontend/lib/mih_components/mih_providers/patient_manager_provider.dart b/Frontend/lib/mih_components/mih_providers/patient_manager_provider.dart index 160faaf8..03761c94 100644 --- a/Frontend/lib/mih_components/mih_providers/patient_manager_provider.dart +++ b/Frontend/lib/mih_components/mih_providers/patient_manager_provider.dart @@ -15,6 +15,7 @@ class PatientManagerProvider extends ChangeNotifier { List? consultationNotes; List? patientDocuments; List? patientClaimsDocuments; + List patientSearchResults = []; PatientManagerProvider({ this.patientProfileIndex = 0, @@ -75,4 +76,9 @@ class PatientManagerProvider extends ChangeNotifier { this.patientClaimsDocuments = patientClaimsDocuments ?? []; notifyListeners(); } + + void setPatientSearchResults({required List patientSearchResults}) { + this.patientSearchResults = patientSearchResults; + notifyListeners(); + } } diff --git a/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart b/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart index b8c7746e..acfb992f 100644 --- a/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart +++ b/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart @@ -1,5 +1,4 @@ import 'package:go_router/go_router.dart'; -import 'package:ken_logger/ken_logger.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_icons.dart'; @@ -78,9 +77,7 @@ class _MihBusinessHomeState extends State // return []; // Return empty list if data isn't ready // } List> temp = []; - KenLogger.success("here"); if (mzansiProfileProvider.business == null && !widget.isLoading) { - KenLogger.success("here"); temp.add({ "Setup Business": MzansiSetupBusinessProfileTile( packageSize: packageSize, diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart index e15563b8..70d18e09 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart @@ -167,6 +167,7 @@ class _MihBusinessUserSearchState extends State { } Widget getBody(double width) { + // dscvds return MihSingleChildScroll( child: Column(mainAxisSize: MainAxisSize.max, children: [ Padding( @@ -187,7 +188,6 @@ class _MihBusinessUserSearchState extends State { searchController.clear(); userSearch = ""; }); - submitUserForm(); }, searchFocusNode: _searchFocusNode, ), diff --git a/Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_mih_patient_search_list.dart b/Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_mih_patient_search_list.dart index 68f98a06..bcbfb931 100644 --- a/Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_mih_patient_search_list.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_mih_patient_search_list.dart @@ -1,38 +1,25 @@ -import 'dart:convert'; import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_access_controls_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.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; +import 'package:provider/provider.dart'; class BuildMihPatientSearchList extends StatefulWidget { - final List 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 @@ -48,90 +35,6 @@ class _BuildPatientsListState extends State { TextEditingController accessStatusController = TextEditingController(); final baseAPI = AppEnviroment.baseApiUrl; - Future addPatientAccessAPICall(int index) async { - var response = await http.post( - Uri.parse("$baseAPI/access-requests/insert/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "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 addAccessReviewNotificationAPICall(int index) async { - var response = await http.post( - Uri.parse("$baseAPI/notifications/insert/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "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, @@ -141,10 +44,12 @@ class _BuildPatientsListState extends State { ); } - Future hasAccessToProfile(int index) async { + Future hasAccessToProfile(MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, int index) async { var hasAccess = false; await MIHApiCalls.checkBusinessAccessToPatient( - widget.business!.business_id, widget.patients[index].app_id) + profileProvider.business!.business_id, + patientManagerProvider.patientSearchResults[index].app_id) .then((results) { if (results.isEmpty) { setState(() { @@ -163,10 +68,12 @@ class _BuildPatientsListState extends State { return hasAccess; } - Future getAccessStatusOfProfile(int index) async { + Future getAccessStatusOfProfile(MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, int index) async { var accessStatus = ""; await MIHApiCalls.checkBusinessAccessToPatient( - widget.business!.business_id, widget.patients[index].app_id) + profileProvider.business!.business_id, + patientManagerProvider.patientSearchResults[index].app_id) .then((results) { if (results.isEmpty) { setState(() { @@ -181,15 +88,22 @@ class _BuildPatientsListState extends State { return accessStatus; } - void patientProfileChoicePopUp(int index) async { + void patientProfileChoicePopUp( + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + int index, + ) async { var hasAccess = false; String accessStatus = ""; - await hasAccessToProfile(index).then((result) { + await hasAccessToProfile(profileProvider, patientManagerProvider, index) + .then((result) { setState(() { hasAccess = result; }); }); - await getAccessStatusOfProfile(index).then((result) { + await getAccessStatusOfProfile( + profileProvider, patientManagerProvider, index) + .then((result) { setState(() { accessStatus = result; }); @@ -197,13 +111,22 @@ class _BuildPatientsListState extends State { if (accessStatus == "") { accessStatus = "No Access"; } - var idStars = '*' * (13 - 6); - String startedOutPatientIdNo = - "${widget.patients[index].id_no.substring(0, 6)}$idStars"; + String patientIdNo = + patientManagerProvider.patientSearchResults[index].id_no; + String displayedIdNo; + + if (patientIdNo.length >= 6) { + var idStars = '*' * (patientIdNo.length - 6); + displayedIdNo = "${patientIdNo.substring(0, 6)}$idStars"; + } else { + displayedIdNo = "${patientIdNo}******"; + } setState(() { - idController.text = startedOutPatientIdNo; - fnameController.text = widget.patients[index].first_name; - lnameController.text = widget.patients[index].last_name; + idController.text = displayedIdNo; + fnameController.text = + patientManagerProvider.patientSearchResults[index].first_name; + lnameController.text = + patientManagerProvider.patientSearchResults[index].last_name; accessStatusController.text = accessStatus.toUpperCase(); }); //print(accessStatus); @@ -362,17 +285,21 @@ class _BuildPatientsListState extends State { visible: hasAccess, child: Center( child: MihButton( - onPressed: () { + onPressed: () async { if (hasAccess) { + await MihPatientServices().getPatientDetails( + patientManagerProvider + .patientSearchResults[index].app_id, + patientManagerProvider); context.pop(); - context.pushNamed('patientManagerPatient', - extra: PatientViewArguments( - widget.signedInUser, - widget.patients[index], - widget.businessUser, - widget.business, - "business", - )); + context.pushNamed( + 'patientManagerPatient', + ); + // context.pushNamed( + // 'patientPatient', + // extra: patientManagerProvider + // .patientSearchResults![index].app_id, + // ); // Navigator.of(context) // .pushNamed('/patient-manager/patient', // arguments: PatientViewArguments( @@ -407,17 +334,19 @@ class _BuildPatientsListState extends State { visible: !hasAccess && accessStatus == "No Access", child: Center( child: MihButton( - onPressed: () { - MIHApiCalls.addPatientAccessAPICall( - widget.business!.business_id, - widget.patients[index].app_id, + onPressed: () async { + await MihAccessControlsServices + .addPatientAccessAPICall( + profileProvider.business!.business_id, + patientManagerProvider + .patientSearchResults[index].app_id, "patient", - widget.business!.Name, - widget.personalSelected, + profileProvider.business!.Name, + patientManagerProvider.personalMode, BusinessArguments( - widget.signedInUser, - widget.businessUser, - widget.business, + profileProvider.user!, + profileProvider.businessUser, + profileProvider.business, ), context, ); @@ -443,15 +372,16 @@ class _BuildPatientsListState extends State { visible: !hasAccess && accessStatus == "declined", child: Center( child: MihButton( - onPressed: () { - MIHApiCalls.reapplyPatientAccessAPICall( - widget.business!.business_id, - widget.patients[index].app_id, - widget.personalSelected, + onPressed: () async { + await MIHApiCalls.reapplyPatientAccessAPICall( + profileProvider.business!.business_id, + patientManagerProvider + .patientSearchResults[index].app_id, + patientManagerProvider.personalMode, BusinessArguments( - widget.signedInUser, - widget.businessUser, - widget.business, + profileProvider.user!, + profileProvider.businessUser, + profileProvider.business, ), context, ); @@ -491,20 +421,17 @@ class _BuildPatientsListState extends State { ); } - 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") { + Widget isMainMember( + PatientManagerProvider patientManagerProvider, int index) { + if (patientManagerProvider + .patientSearchResults[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}", + "${patientManagerProvider.patientSearchResults[index].first_name} ${patientManagerProvider.patientSearchResults[index].last_name}", style: TextStyle( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -523,7 +450,7 @@ class _BuildPatientsListState extends State { } else { return Text( // "$firstLetterFName$fnameStar $firstLetterLName$lnameStar", - "${widget.patients[index].first_name} ${widget.patients[index].last_name}", + "${patientManagerProvider.patientSearchResults[index].first_name} ${patientManagerProvider.patientSearchResults[index].last_name}", style: TextStyle( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -532,23 +459,37 @@ class _BuildPatientsListState extends State { } } - Widget hasMedicalAid(int index) { + Widget hasMedicalAid( + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + int index, + ) { + String patientIdNo = + patientManagerProvider.patientSearchResults[index].id_no; + String displayedIdNo; 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") { + if (patientIdNo.length >= 6) { + var idStars = '*' * (patientIdNo.length - 6); + displayedIdNo = "${patientIdNo.substring(0, 6)}$idStars"; + } else { + // If ID is shorter than 6 characters, just show it with stars + displayedIdNo = "${patientIdNo}******"; + } + + if (patientManagerProvider.patientSearchResults[index].medical_aid == + "Yes") { return ListTile( - title: isMainMember(index), + title: isMainMember(patientManagerProvider, index), subtitle: Text( - "ID No.: $startedOutPatientIdNo\nMedical Aid No.: $medAidNoStar", + "ID No.: $displayedIdNo\nMedical Aid No.: $medAidNoStar", style: TextStyle( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), ), onTap: () { - patientProfileChoicePopUp(index); + patientProfileChoicePopUp( + profileProvider, patientManagerProvider, index); // setState(() { // appointmentPopUp(index); // // Add popup to add patienmt to queue @@ -565,16 +506,17 @@ class _BuildPatientsListState extends State { ); } else { return ListTile( - title: isMainMember(index), + title: isMainMember(patientManagerProvider, index), subtitle: Text( - "ID No.: $startedOutPatientIdNo\nMedical Aid No.: $medAidNoStar", + "ID No.: $displayedIdNo\nMedical Aid No.: $medAidNoStar", style: TextStyle( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), ), onTap: () { - patientProfileChoicePopUp(index); + patientProfileChoicePopUp( + profileProvider, patientManagerProvider, index); // setState(() { // appointmentPopUp(index); // // Navigator.of(context).pushNamed('/patient-manager/patient', @@ -599,26 +541,35 @@ class _BuildPatientsListState extends State { fnameController.dispose(); lnameController.dispose(); accessStatusController.dispose(); + PatientManagerProvider patientManagerProvider = + context.read(); + patientManagerProvider.setPatientSearchResults(patientSearchResults: []); 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"), + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, index) { + return Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + itemCount: patientManagerProvider.patientSearchResults.length, + itemBuilder: (context, index) { + KenLogger.success( + "Search Results Count: ${patientManagerProvider.patientSearchResults.length}"); + return hasMedicalAid( + profileProvider, patientManagerProvider, index); + }, ); }, - itemCount: widget.patients.length, - itemBuilder: (context, index) { - //final patient = widget.patients[index].id_no.contains(widget.searchString); - //print(index); - return hasMedicalAid(index); - }, ); } } diff --git a/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/mih_patient_search.dart b/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/mih_patient_search.dart index 10d39928..a795732a 100644 --- a/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/mih_patient_search.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/mih_patient_search.dart @@ -1,32 +1,21 @@ 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_providers/patient_manager_provider.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_patient_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_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'; +import 'package:provider/provider.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 @@ -40,71 +29,44 @@ class _MihPatientSearchState extends State { bool hasSearchedBefore = false; String _mihPatientSearchString = ""; String baseUrl = AppEnviroment.baseApiUrl; - late Future> _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 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, - ), - ); - } - }, - ), - ]), + return Consumer( + builder: (BuildContext context, + PatientManagerProvider patientManagerProvider, Widget? child) { + 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(patientManagerProvider); + }, + onClearIconTap: () { + setState(() { + _mihPatientSearchController.clear(); + _mihPatientSearchString = ""; + }); + patientManagerProvider + .setPatientSearchResults(patientSearchResults: []); + }, + searchFocusNode: _searchFocusNode, + ), + ), + //spacer + const SizedBox(height: 10), + + displayPatientList(patientManagerProvider, _mihPatientSearchString), + ]), + ); + }, ); } @@ -121,16 +83,12 @@ class _MihPatientSearchState extends State { return templist; } - Widget displayPatientList(List 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 != "") { + Widget displayPatientList( + PatientManagerProvider patientManagerProvider, String searchString) { + if (patientManagerProvider.patientSearchResults.isNotEmpty) { + return BuildMihPatientSearchList(); + } else if (patientManagerProvider.patientSearchResults.isEmpty && + searchString != "") { return Column( children: [ const SizedBox(height: 50), @@ -195,17 +153,6 @@ class _MihPatientSearchState extends State { 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"), ], ), ), @@ -213,30 +160,18 @@ class _MihPatientSearchState extends State { ], ), ); - // 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() { + Future submitPatientSearch( + PatientManagerProvider patientManagerProvider) async { if (_mihPatientSearchController.text != "") { setState(() { _mihPatientSearchString = _mihPatientSearchController.text; - _mihPatientSearchResults = - MIHApiCalls.fetchPatients(_mihPatientSearchString); hasSearchedBefore = true; }); + await MihPatientServices.searchPatients( + patientManagerProvider, _mihPatientSearchString); } } @@ -257,7 +192,6 @@ class _MihPatientSearchState extends State { @override void initState() { super.initState(); - _mihPatientSearchResults = MIHApiCalls.fetchPatients("abc"); } @override diff --git a/Frontend/lib/mih_packages/patient_manager/pat_manager/pat_manager.dart b/Frontend/lib/mih_packages/patient_manager/pat_manager/pat_manager.dart index 2c0fe380..ff3add3b 100644 --- a/Frontend/lib/mih_packages/patient_manager/pat_manager/pat_manager.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_manager/pat_manager.dart @@ -5,6 +5,7 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ 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_components/mih_providers/patient_manager_provider.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'; @@ -42,7 +43,7 @@ class _PatManagerState extends State { mihCalendarProvider.selectedDay, mihCalendarProvider, ); - MihPatientServices().getPatientAccessListOfBusiness( + await MihPatientServices().getPatientAccessListOfBusiness( patientManagerProvider, profileProvider.business!.business_id); } setState(() { @@ -82,13 +83,9 @@ class _PatManagerState extends State { onTap: () { patientManagerProvider.setPatientProfileIndex(0); patientManagerProvider.setPatientManagerIndex(0); - if (!patientManagerProvider.personalMode) { - context.pop(); - } else { - context.goNamed( - 'mihHome', - ); - } + context.goNamed( + 'mihHome', + ); FocusScope.of(context).unfocus(); }, ); @@ -104,6 +101,9 @@ class _PatManagerState extends State { }; temp[const Icon(Icons.search)] = () { + context + .read() + .setPatientSearchResults(patientSearchResults: []); context.read().setPatientManagerIndex(2); }; return MihPackageTools( @@ -117,13 +117,7 @@ class _PatManagerState extends State { List toolBodies = [ WaitingRoom(), MyPatientList(), - Placeholder(), - // MihPatientSearch( - // signedInUser: widget.arguments.signedInUser, - // business: widget.arguments.business, - // personalSelected: widget.arguments.personalSelected, - // businessUser: widget.arguments.businessUser, - // ), + MihPatientSearch(), ]; return toolBodies; } diff --git a/Frontend/lib/mih_services/mih_access_controls_services.dart b/Frontend/lib/mih_services/mih_access_controls_services.dart index 65718929..322031f9 100644 --- a/Frontend/lib/mih_services/mih_access_controls_services.dart +++ b/Frontend/lib/mih_services/mih_access_controls_services.dart @@ -2,10 +2,13 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.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/patient_access.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_providers/mih_access_controlls_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_notification_services.dart'; import 'package:supertokens_flutter/http.dart' as http; class MihAccessControlsServices { @@ -32,6 +35,98 @@ class MihAccessControlsServices { } } + /// This function is used to create patient access and trigger notification to patient + /// + /// Patameters:- + /// String business_id, + /// String app_id, + /// String type, + /// String requested_by, + /// BuildContext context, + /// + /// Returns void (triggers notification of success 201). + static Future addPatientAccessAPICall( + String business_id, + String app_id, + String type, + String requested_by, + bool personalSelected, + BusinessArguments args, + BuildContext context, + ) async { + var response = await http.post( + Uri.parse("${AppEnviroment.baseApiUrl}/access-requests/insert/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + // business_id: str + // app_id: str + // type: str + // requested_by: str + body: jsonEncode({ + "business_id": business_id, + "app_id": app_id, + "type": type, + "requested_by": requested_by, + }), + ); + if (response.statusCode == 201) { + await MihNotificationApis.addAccessRequestNotificationAPICall( + app_id, requested_by, personalSelected, args, context); + } else { + internetConnectionPopUp(context); + } + } + + /// This function is used to reapply for access to patient. + /// + /// Patameters:- + /// String business_id, + /// String app_id, + /// BuildContext context, + /// + /// Returns void (on success 200 navigate to /mih-access ). + static Future reapplyPatientAccessAPICall( + String business_id, + String app_id, + bool personalSelected, + BusinessArguments args, + BuildContext context, + ) async { + var response = await http.put( + Uri.parse("${AppEnviroment.baseApiUrl}/access-requests/re-apply/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + // business_id: str + // app_id: str + // status: str + // approved_by: str + body: jsonEncode({ + "business_id": business_id, + "app_id": app_id, + }), + ); + if (response.statusCode == 200) { + await MihNotificationApis.reapplyAccessRequestNotificationAPICall( + app_id, personalSelected, args, context); + //notification here + } else { + internetConnectionPopUp(context); + } + } + + static void internetConnectionPopUp(BuildContext context) { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage( + errorType: "Internet Connection", + ); + }, + ); + } + /// This function is used to UPDATE access the business has. /// /// Patameters:- diff --git a/Frontend/lib/mih_services/mih_patient_services.dart b/Frontend/lib/mih_services/mih_patient_services.dart index 8556a80f..a4b26c4d 100644 --- a/Frontend/lib/mih_services/mih_patient_services.dart +++ b/Frontend/lib/mih_services/mih_patient_services.dart @@ -1,7 +1,6 @@ import 'dart:convert'; import 'package:file_picker/file_picker.dart'; -import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/files.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/notes.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart'; @@ -26,7 +25,6 @@ class MihPatientServices { ); if (response.statusCode == 200) { String body = response.body; - KenLogger.success(response.body); var jsonBody = jsonDecode(body); Patient patient = Patient.fromJson(jsonBody); patientManagerProvider.setSelectedPatient(selectedPatient: patient); @@ -36,6 +34,24 @@ class MihPatientServices { } } + static Future> searchPatients( + PatientManagerProvider patientManagerProvider, + String search, + ) async { + final response = await http + .get(Uri.parse("${AppEnviroment.baseApiUrl}/patients/search/$search")); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List patients = + List.from(l.map((model) => Patient.fromJson(model))); + patientManagerProvider.setPatientSearchResults( + patientSearchResults: patients); + return patients; + } else { + throw Exception('failed to load patients'); + } + } + Future addPatientService( String id_no, String fname, diff --git a/Frontend/lib/mih_services/mih_service_calls.dart b/Frontend/lib/mih_services/mih_service_calls.dart index 4cda4a90..d0de0899 100644 --- a/Frontend/lib/mih_services/mih_service_calls.dart +++ b/Frontend/lib/mih_services/mih_service_calls.dart @@ -274,12 +274,10 @@ class MIHApiCalls { /// Patameters: String dsearch. /// /// Returns List. + static Future> fetchPatients(String search) async { final response = await http .get(Uri.parse("${AppEnviroment.baseApiUrl}/patients/search/$search")); - // errorCode = response.statusCode.toString(); - // errorBody = response.body; - if (response.statusCode == 200) { Iterable l = jsonDecode(response.body); List patients =