diff --git a/Frontend/patient_manager/lib/components/buildPatientQueueList.dart b/Frontend/patient_manager/lib/components/buildPatientQueueList.dart new file mode 100644 index 00000000..181ecd96 --- /dev/null +++ b/Frontend/patient_manager/lib/components/buildPatientQueueList.dart @@ -0,0 +1,110 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:patient_manager/env/env.dart'; +import 'package:patient_manager/main.dart'; +import 'package:patient_manager/objects/appUser.dart'; +import 'package:patient_manager/objects/arguments.dart'; +import 'package:patient_manager/objects/patientQueue.dart'; +import 'package:patient_manager/objects/patients.dart'; +import 'package:supertokens_flutter/http.dart' as http; + +class BuildPatientQueueList extends StatefulWidget { + final List patientQueue; + final AppUser signedInUser; + + const BuildPatientQueueList({ + super.key, + required this.patientQueue, + required this.signedInUser, + }); + + @override + State createState() => _BuildPatientsListState(); +} + +class _BuildPatientsListState extends State { + String baseAPI = AppEnviroment.baseApiUrl; + + Future fetchPatients(String app_id) async { + //print("pat man drawer: " + endpointUserData + widget.userEmail); + + var response = await http.get(Uri.parse("$baseAPI/patients/$app_id")); + + // print(response.statusCode); + // print(response.body); + if (response.statusCode == 200) { + // print("here"); + String body = response.body; + var decodedData = jsonDecode(body); + Patient u = Patient.fromJson(decodedData); + // print(u.email); + //setState(() { + //_widgetOptions = setLayout(u); + //}); + return u; + } else { + throw Exception("Error: GetUserData status code ${response.statusCode}"); + } + } + + Widget displayQueue(int index) { + String title = + widget.patientQueue[index].date_time.split('T')[1].substring(0, 5); + String subtitle = + "Name: ${widget.patientQueue[index].first_name} ${widget.patientQueue[index].last_name}\nID No.: ${widget.patientQueue[index].id_no}\nMedical Aid No: "; + if (widget.patientQueue[index].medical_aid_no == "") { + subtitle += "No Medical Aid"; + } else { + subtitle += widget.patientQueue[index].medical_aid_no; + } + return ListTile( + title: Text( + "Appointment: $title", + style: TextStyle( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + subtitle: Text( + subtitle, + style: TextStyle( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + onTap: () { + Patient selectedPatient; + fetchPatients(widget.patientQueue[index].app_id).then( + (result) { + setState(() { + selectedPatient = result; + Navigator.of(context).pushNamed('/patient-manager/patient', + arguments: PatientViewArguments( + widget.signedInUser, selectedPatient, "business")); + }); + }, + ); + }, + trailing: Icon( + Icons.arrow_forward, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ); + } + + @override + Widget build(BuildContext context) { + return ListView.separated( + separatorBuilder: (BuildContext context, index) { + return Divider( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ); + }, + itemCount: widget.patientQueue.length, + itemBuilder: (context, index) { + //final patient = widget.patients[index].id_no.contains(widget.searchString); + //print(index); + return displayQueue(index); + }, + ); + } +} diff --git a/Frontend/patient_manager/lib/objects/patientQueue.dart b/Frontend/patient_manager/lib/objects/patientQueue.dart new file mode 100644 index 00000000..7013a699 --- /dev/null +++ b/Frontend/patient_manager/lib/objects/patientQueue.dart @@ -0,0 +1,51 @@ +class PatientQueue { + final int idpatient_queue; + final String business_id; + final String app_id; + final String date_time; + final String access; + final String id_no; + final String first_name; + final String last_name; + final String medical_aid_no; + + const PatientQueue({ + required this.idpatient_queue, + required this.business_id, + required this.app_id, + required this.date_time, + required this.access, + required this.id_no, + required this.first_name, + required this.last_name, + required this.medical_aid_no, + }); + + factory PatientQueue.fromJson(Map json) { + return switch (json) { + { + "idpatient_queue": int idpatient_queue, + 'business_id': String business_id, + 'app_id': String app_id, + 'date_time': String date_time, + 'access': String access, + 'id_no': String id_no, + 'first_name': String first_name, + 'last_name': String last_name, + 'medical_aid_no': String medical_aid_no, + } => + PatientQueue( + idpatient_queue: idpatient_queue, + business_id: business_id, + app_id: app_id, + date_time: date_time, + access: access, + id_no: id_no, + first_name: first_name, + last_name: last_name, + medical_aid_no: medical_aid_no, + ), + _ => throw const FormatException('Failed to load album.'), + }; + } +} diff --git a/Frontend/patient_manager/lib/pages/patientManager.dart b/Frontend/patient_manager/lib/pages/patientManager.dart index 15f24d14..2388a642 100644 --- a/Frontend/patient_manager/lib/pages/patientManager.dart +++ b/Frontend/patient_manager/lib/pages/patientManager.dart @@ -1,12 +1,16 @@ import 'dart:async'; import 'dart:convert'; +import 'package:intl/intl.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:patient_manager/components/buildPatientList.dart'; +import 'package:patient_manager/components/buildPatientQueueList.dart'; import 'package:patient_manager/components/mihAppBar.dart'; import 'package:patient_manager/components/mihLoadingCircle.dart'; -import 'package:patient_manager/objects/appUser.dart'; +import 'package:patient_manager/components/myDateInput.dart'; +import 'package:patient_manager/objects/arguments.dart'; +import 'package:patient_manager/objects/patientQueue.dart'; import 'package:supertokens_flutter/http.dart' as http; import 'package:patient_manager/components/mySearchInput.dart'; import 'package:patient_manager/env/env.dart'; @@ -14,11 +18,11 @@ import 'package:patient_manager/main.dart'; import 'package:patient_manager/objects/patients.dart'; class PatientManager extends StatefulWidget { - final AppUser signedInUser; - + //final AppUser signedInUser; + final BusinessArguments arguments; const PatientManager({ super.key, - required this.signedInUser, + required this.arguments, }); @override @@ -28,6 +32,8 @@ class PatientManager extends StatefulWidget { // class _PatientManagerState extends State { TextEditingController searchController = TextEditingController(); + TextEditingController queueDateController = TextEditingController(); + String baseUrl = AppEnviroment.baseApiUrl; final FocusNode _focusNode = FocusNode(); @@ -37,11 +43,12 @@ class _PatientManagerState extends State { String searchString = ""; late Future> patientSearchResults; + late Future> patientQueueResults; - Future> fetchPatients(String search) async { + Future> fetchPatientQueue(String date) async { //print("Patien manager page: $endpoint"); - final response = - await http.get(Uri.parse("$baseUrl/patients/search/$search")); + final response = await http.get(Uri.parse( + "$baseUrl/queue/patients/${widget.arguments.businessUser!.business_id}")); // print("Here"); // print("Body: ${response.body}"); // print("Code: ${response.statusCode}"); @@ -52,20 +59,49 @@ class _PatientManagerState extends State { //print("Here1"); Iterable l = jsonDecode(response.body); //print("Here2"); + List patientQueue = List.from( + l.map((model) => PatientQueue.fromJson(model))); + //print("Here3"); + //print(patientQueue); + return patientQueue; + } else { + throw Exception('failed to load patients'); + } + } + + List filterQueueResults( + List queueList, String query) { + List templist = []; + //print(query); + for (var item in queueList) { + if (item.date_time.contains(query)) { + //print(item.medical_aid_no); + templist.add(item); + } + } + return templist; + } + + Future> fetchPatients(String search) async { + final response = + await http.get(Uri.parse("$baseUrl/patients/search/$search")); + errorCode = response.statusCode.toString(); + errorBody = response.body; + + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); List patients = List.from(l.map((model) => Patient.fromJson(model))); - // print("Here3"); - // print(patients); return patients; } else { throw Exception('failed to load patients'); } } - List filterSearchResults(List mainList, String query) { + List filterSearchResults(List patList, String query) { List templist = []; //print(query); - for (var item in mainList) { + for (var item in patList) { if (item.id_no.contains(searchString) || item.medical_aid_no.contains(searchString)) { //print(item.medical_aid_no); @@ -75,14 +111,7 @@ class _PatientManagerState extends State { return templist; } - void submitForm() { - setState(() { - searchString = searchController.text; - patientSearchResults = fetchPatients(searchString); - }); - } - - Widget displayList(List patientsList, String searchString) { + Widget displayPatientList(List patientsList, String searchString) { if (searchString.isNotEmpty && searchString != "") { return Container( height: 500, @@ -96,12 +125,12 @@ class _PatientManagerState extends State { ), child: BuildPatientsList( patients: patientsList, - signedInUser: widget.signedInUser, + signedInUser: widget.arguments.signedInUser, ), ); } return Container( - height: 500, + //height: 500, decoration: BoxDecoration( color: MzanziInnovationHub.of(context)!.theme.primaryColor(), borderRadius: BorderRadius.circular(25.0), @@ -128,106 +157,238 @@ class _PatientManagerState extends State { onKeyEvent: (event) async { if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.enter) { - submitForm(); + submitPatientForm(); } }, - child: Padding( - padding: const EdgeInsets.only( - left: 25, - right: 25, - bottom: 25, - ), - child: SizedBox( - width: w, - height: h, - child: Column(mainAxisSize: MainAxisSize.max, children: [ - //spacer - const SizedBox(height: 10), - MySearchField( - controller: searchController, - hintText: "ID or Medical Aid No. Search", - required: false, - editable: true, - onTap: () { - submitForm(); - }, - onChanged: (value) {}, - ), - //spacer - const SizedBox(height: 10), - FutureBuilder( - future: patientSearchResults, - builder: (context, snapshot) { - //print("patient Liust ${snapshot.data}"); - if (snapshot.connectionState == ConnectionState.waiting) { - return Container( - height: 500, - decoration: BoxDecoration( - color: - MzanziInnovationHub.of(context)!.theme.primaryColor(), - borderRadius: BorderRadius.circular(25.0), - border: Border.all( - color: MzanziInnovationHub.of(context)! - .theme - .secondaryColor(), - width: 3.0), - ), - child: const Mihloadingcircle(), - ); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - List patientsList; - if (searchString == "") { - patientsList = []; - } else { - patientsList = - filterSearchResults(snapshot.data!, searchString); - //print(patientsList); - } - - return Expanded( - child: displayList(patientsList, searchString), - ); + child: SizedBox( + width: w, + height: 600, + child: Column(mainAxisSize: MainAxisSize.max, children: [ + const SizedBox(height: 15), + const Text( + "Patient Search", + style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), + ), + //spacer + const SizedBox(height: 10), + MySearchField( + controller: searchController, + hintText: "ID or Medical Aid No. Search", + required: false, + editable: true, + onTap: () { + submitPatientForm(); + }, + onChanged: (value) {}, + ), + //spacer + const SizedBox(height: 10), + FutureBuilder( + future: patientSearchResults, + builder: (context, snapshot) { + //print("patient Liust ${snapshot.data}"); + if (snapshot.connectionState == ConnectionState.waiting) { + return Container( + //height: 500, + decoration: BoxDecoration( + color: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + borderRadius: BorderRadius.circular(25.0), + border: Border.all( + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + width: 3.0), + ), + child: const Mihloadingcircle(), + ); + } else if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData) { + List patientsList; + if (searchString == "") { + patientsList = []; } else { - return Container( - height: 500, - decoration: BoxDecoration( - color: - MzanziInnovationHub.of(context)!.theme.primaryColor(), - borderRadius: BorderRadius.circular(25.0), - border: Border.all( + patientsList = + filterSearchResults(snapshot.data!, searchString); + //print(patientsList); + } + + return Expanded( + child: displayPatientList(patientsList, searchString), + ); + } else { + return Container( + //height: 500, + decoration: BoxDecoration( + color: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + borderRadius: BorderRadius.circular(25.0), + border: Border.all( + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + width: 3.0), + ), + child: Center( + child: Text( + "$errorCode: Error pulling Patients Data\n$baseUrl/patients/search/$searchString\n$errorBody", + style: TextStyle( + fontSize: 25, color: MzanziInnovationHub.of(context)! .theme - .secondaryColor(), - width: 3.0), + .errorColor()), + textAlign: TextAlign.center, ), - child: Center( - child: Text( - "$errorCode: Error pulling Patients Data\n$baseUrl${widget.signedInUser.email}\n$errorBody", - style: TextStyle( - fontSize: 25, - color: MzanziInnovationHub.of(context)! - .theme - .errorColor()), - textAlign: TextAlign.center, - ), - ), - ); - } - }, - ), - ]), + ), + ); + } + }, + ), + ]), + ), + ); + } + + Widget displayQueueList(List patientQueueList) { + if (patientQueueList.isNotEmpty) { + return Container( + height: 500, + decoration: BoxDecoration( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + borderRadius: BorderRadius.circular(25.0), + border: Border.all( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + width: 3.0, + ), + ), + child: BuildPatientQueueList( + patientQueue: patientQueueList, + signedInUser: widget.arguments.signedInUser, + ), + ); + } + return Container( + //height: 500, + decoration: BoxDecoration( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + borderRadius: BorderRadius.circular(25.0), + border: Border.all( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + width: 3.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, ), ), ); } + Widget patientQueue(double w, double h) { + return SizedBox( + width: w, + height: 600, + child: Column(mainAxisSize: MainAxisSize.max, children: [ + const SizedBox(height: 15), + const Text( + "Waiting Room", + style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + MyDateField( + controller: queueDateController, + LableText: "Date", + required: false, + ), + //spacer + const SizedBox(height: 10), + FutureBuilder( + future: fetchPatientQueue(queueDateController.text), + builder: (context, snapshot) { + print("patient Queue List ${snapshot.hasData}"); + if (snapshot.connectionState == ConnectionState.waiting) { + return Container( + //height: 500, + decoration: BoxDecoration( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + borderRadius: BorderRadius.circular(25.0), + border: Border.all( + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + width: 3.0), + ), + child: const Mihloadingcircle(), + ); + } else if (snapshot.connectionState == ConnectionState.done) { + List patientQueueList; + // if (searchString == "") { + // patientQueueList = []; + // } else { + patientQueueList = filterQueueResults( + snapshot.requireData, queueDateController.text); + // print(patientQueueList); + // } + + return Expanded( + child: displayQueueList(patientQueueList), + ); + } else { + return Container( + //height: 500, + decoration: BoxDecoration( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + borderRadius: BorderRadius.circular(25.0), + border: Border.all( + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + width: 3.0), + ), + child: Center( + child: Text( + "$errorCode: Error pulling Patients Data\n$baseUrl/patients/search/$searchString\n$errorBody", + style: TextStyle( + fontSize: 25, + color: MzanziInnovationHub.of(context)! + .theme + .errorColor()), + textAlign: TextAlign.center, + ), + ), + ); + } + }, + ), + ]), + ); + } + + void submitPatientForm() { + setState(() { + searchString = searchController.text; + patientSearchResults = fetchPatients(searchString); + }); + } + @override void initState() { // errorCode = ""; // errorBody = ""; //print("patient manager page: ${widget.userEmail}"); + var now = DateTime.now(); + var formatter = DateFormat('yyyy-MM-dd'); + String formattedDate = formatter.format(now); + patientSearchResults = fetchPatients("abc"); + //patientQueueResults = fetchPatientQueue(formattedDate); + setState(() { + queueDateController.text = formattedDate; + }); super.initState(); } @@ -260,7 +421,27 @@ class _PatientManagerState extends State { // color: MzanziInnovationHub.of(context)!.theme.primaryColor(), // ), // ), - body: patientSearch(screenWidth, screenHeight), + body: SizedBox( + width: double.infinity, + child: Wrap( + spacing: 10.0, + runSpacing: 10.0, + direction: Axis.horizontal, + alignment: WrapAlignment.center, + runAlignment: WrapAlignment.center, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + SizedBox( + width: 660, + child: patientSearch(screenWidth, screenHeight), + ), + SizedBox( + width: 660, + child: patientQueue(screenWidth, screenHeight), + ), + ], + ), + ), ); } } diff --git a/Frontend/patient_manager/pubspec.lock b/Frontend/patient_manager/pubspec.lock index 5b57a606..4e8f099f 100644 --- a/Frontend/patient_manager/pubspec.lock +++ b/Frontend/patient_manager/pubspec.lock @@ -489,7 +489,7 @@ packages: source: hosted version: "4.0.2" intl: - dependency: transitive + dependency: "direct main" description: name: intl sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf diff --git a/Frontend/patient_manager/pubspec.yaml b/Frontend/patient_manager/pubspec.yaml index 23a6dddc..caeff7e2 100644 --- a/Frontend/patient_manager/pubspec.yaml +++ b/Frontend/patient_manager/pubspec.yaml @@ -46,6 +46,7 @@ dependencies: mysql_client: ^0.0.27 args: 2.5.0 gif: ^2.3.0 + intl: ^0.19.0 dev_dependencies: flutter_test: