app files restructure

This commit is contained in:
2024-11-14 11:46:50 +02:00
parent c07f0c25c5
commit 469a4b0383
312 changed files with 592 additions and 546 deletions

View File

@@ -0,0 +1,380 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import '../../main.dart';
import 'package:supertokens_flutter/http.dart' as http;
import '../../mih_apis/mih_api_calls.dart';
import '../../mih_components/mih_calendar.dart';
import '../../mih_components/mih_inputs_and_buttons/mih_dropdown_input.dart';
import '../../mih_components/mih_layout/mih_action.dart';
import '../../mih_components/mih_layout/mih_body.dart';
import '../../mih_components/mih_layout/mih_header.dart';
import '../../mih_components/mih_layout/mih_layout_builder.dart';
import '../../mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import '../../mih_env/env.dart';
import '../../mih_objects/access_request.dart';
import '../../mih_objects/app_user.dart';
import '../../mih_objects/patient_queue.dart';
import '../access_review/builder/build_access_request_list.dart';
import 'builder/build_appointment_list.dart';
class Appointments extends StatefulWidget {
final AppUser signedInUser;
const Appointments({
super.key,
required this.signedInUser,
});
@override
State<Appointments> createState() => _PatientAccessRequestState();
}
class _PatientAccessRequestState extends State<Appointments> {
TextEditingController filterController = TextEditingController();
TextEditingController appointmentDateController = 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<AccessRequest>> accessRequestResults;
late Future<List<PatientQueue>> personalQueueResults;
Future<List<AccessRequest>> fetchAccessRequests() async {
//print("Patien manager page: $endpoint");
final response = await http.get(
Uri.parse("$baseUrl/access-requests/${widget.signedInUser.app_id}"));
// print("Here");
// print("Body: ${response.body}");
// print("Code: ${response.statusCode}");
errorCode = response.statusCode.toString();
errorBody = response.body;
if (response.statusCode == 200) {
//print("Here1");
Iterable l = jsonDecode(response.body);
//print("Here2");
List<AccessRequest> patientQueue = List<AccessRequest>.from(
l.map((model) => AccessRequest.fromJson(model)));
//print("Here3");
//print(patientQueue);
return patientQueue;
} else {
throw Exception('failed to load patients');
}
}
List<AccessRequest> filterSearchResults(List<AccessRequest> accessList) {
List<AccessRequest> templist = [];
for (var item in accessList) {
if (filterController.text == "All") {
if (item.date_time.contains(datefilter)) {
templist.add(item);
}
} else {
if (item.date_time.contains(datefilter) &&
item.access.contains(filterController.text.toLowerCase())) {
templist.add(item);
}
}
}
return templist;
}
Widget displayAccessRequestList(List<AccessRequest> accessRequestList) {
if (accessRequestList.isNotEmpty) {
return BuildAccessRequestList(
signedInUser: widget.signedInUser,
accessRequests: accessRequestList,
// BuildPatientQueueList(
// patientQueue: patientQueueList,
// signedInUser: widget.signedInUser,
// ),
);
} else {
return Center(
child: Text(
"No Request have been made.",
style: TextStyle(
fontSize: 25,
color: MzanziInnovationHub.of(context)!.theme.messageTextColor()),
textAlign: TextAlign.center,
),
);
}
}
Widget viewAccessRequest(double w, double h) {
return Padding(
padding: const EdgeInsets.all(15.0),
child: SizedBox(
width: w,
height: h,
child: Column(mainAxisSize: MainAxisSize.max, children: [
//const SizedBox(height: 15),
const Text(
"Access Request",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
SizedBox(
width: 500,
child: MIHDropdownField(
controller: filterController,
hintText: "Access Types",
dropdownOptions: const ["All", "Approved", "Pending", "Declined"],
required: true,
editable: true,
),
),
const SizedBox(height: 10),
FutureBuilder(
future: accessRequestResults,
builder: (context, snapshot) {
//print("patient Queue List ${snapshot.hasData}");
if (snapshot.connectionState == ConnectionState.waiting) {
return Expanded(
child: 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<AccessRequest> accessRequestList;
accessRequestList = filterSearchResults(snapshot.requireData);
if (accessRequestList.isNotEmpty) {
return BuildAccessRequestList(
signedInUser: widget.signedInUser,
accessRequests: accessRequestList,
);
} else {
return Center(
child: Text(
"No Request have been made.",
style: TextStyle(
fontSize: 25,
color: MzanziInnovationHub.of(context)!
.theme
.messageTextColor()),
textAlign: TextAlign.center,
),
);
}
// return Expanded(
// child: displayAccessRequestList(accessRequestList),
// );
} else {
return Center(
child: Text(
"$errorCode: Error pulling Patients Data\n$baseUrl/queue/patients/\n$errorBody",
style: TextStyle(
fontSize: 25,
color: MzanziInnovationHub.of(context)!
.theme
.errorColor()),
textAlign: TextAlign.center,
),
);
}
},
),
]),
),
);
}
void refreshList() {
if (forceRefresh == true) {
setState(() {
accessRequestResults = fetchAccessRequests();
forceRefresh = false;
});
} else if (selectedDropdown != filterController.text) {
setState(() {
accessRequestResults = fetchAccessRequests();
selectedDropdown = filterController.text;
});
}
// setState(() {
// accessRequestResults = fetchAccessRequests();
// });
}
Widget displayQueueList(List<PatientQueue> patientQueueList) {
if (patientQueueList.isNotEmpty) {
return Expanded(
child: BuildAppointmentList(
patientQueue: patientQueueList,
signedInUser: widget.signedInUser,
),
);
}
return Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 35.0),
child: Center(
child: Text(
"No Appointments for $selectedDay",
style: TextStyle(
fontSize: 25,
color: MzanziInnovationHub.of(context)!.theme.messageTextColor(),
),
textAlign: TextAlign.center,
softWrap: true,
),
),
),
);
}
void checkforchange() {
setState(() {
personalQueueResults = MIHApiCalls.fetchPersonalAppointmentsAPICall(
selectedDay,
widget.signedInUser.app_id,
);
});
}
MIHAction getActionButton() {
return MIHAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).popAndPushNamed(
'/',
arguments: true,
);
},
);
}
MIHHeader getHeader() {
return const MIHHeader(
headerAlignment: MainAxisAlignment.center,
headerItems: [
Text(
"Appointments",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
],
);
}
MIHBody getBody() {
return MIHBody(
borderOn: true,
bodyItems: [
MIHCalendar(
calendarWidth: 500,
rowHeight: 35,
setDate: (value) {
setState(() {
selectedDay = value;
appointmentDateController.text = selectedDay;
});
}),
Divider(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
Row(
mainAxisSize: MainAxisSize.max,
children: [
FutureBuilder(
future: personalQueueResults,
builder: (context, snapshot) {
//return displayQueueList(snapshot.requireData);
if (snapshot.connectionState == ConnectionState.waiting) {
return const Expanded(
child: Center(child: Mihloadingcircle()));
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
return displayQueueList(snapshot.requireData);
} else {
return Center(
child: Text(
"Error pulling appointments",
style: TextStyle(
fontSize: 25,
color: MzanziInnovationHub.of(context)!
.theme
.errorColor()),
textAlign: TextAlign.center,
),
);
}
}),
],
)
],
);
}
@override
void dispose() {
filterController.dispose();
appointmentDateController.dispose();
super.dispose();
}
@override
void initState() {
// selectedDropdown = "All";
// filterController.text = "All";
// filterController.addListener(refreshList);
// setState(() {
// accessRequestResults = fetchAccessRequests();
// });
appointmentDateController.addListener(checkforchange);
setState(() {
personalQueueResults = MIHApiCalls.fetchPersonalAppointmentsAPICall(
selectedDay,
widget.signedInUser.app_id,
);
});
super.initState();
}
@override
Widget build(BuildContext context) {
return MIHLayoutBuilder(
actionButton: getActionButton(),
header: getHeader(),
secondaryActionButton: null,
body: getBody(),
actionDrawer: null,
secondaryActionDrawer: null,
bottomNavBar: null,
pullDownToRefresh: false,
onPullDown: () async {},
);
}
}

View File

@@ -0,0 +1,429 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:supertokens_flutter/http.dart' as http;
import '../../../main.dart';
import '../../../mih_components/mih_inputs_and_buttons/mih_button.dart';
import '../../../mih_components/mih_layout/mih_window.dart';
import '../../../mih_components/mih_pop_up_messages/mih_error_message.dart';
import '../../../mih_components/mih_pop_up_messages/mih_success_message.dart';
import '../../../mih_components/mih_pop_up_messages/mih_warning_message.dart';
import '../../../mih_env/env.dart';
import '../../../mih_objects/access_request.dart';
import '../../../mih_objects/app_user.dart';
class BuildAccessRequestList extends StatefulWidget {
final List<AccessRequest> accessRequests;
final AppUser signedInUser;
const BuildAccessRequestList({
super.key,
required this.accessRequests,
required this.signedInUser,
});
@override
State<BuildAccessRequestList> createState() => _BuildPatientsListState();
}
class _BuildPatientsListState extends State<BuildAccessRequestList> {
String baseAPI = AppEnviroment.baseApiUrl;
late double popUpWidth;
late double? popUpheight;
late double popUpButtonWidth;
late double popUpTitleSize;
late double popUpSubtitleSize;
late double popUpBodySize;
late double popUpIconSize;
late double popUpPaddingSize;
late double width;
late double height;
Future<void> updateAccessAPICall(int index, String accessType) async {
var response = await http.put(
Uri.parse("$baseAPI/access-requests/update/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"business_id": widget.accessRequests[index].business_id,
"app_id": widget.accessRequests[index].app_id,
"date_time": widget.accessRequests[index].date_time,
"access": accessType,
}),
);
if (response.statusCode == 200) {
//Navigator.of(context).pushNamed('/home');
Navigator.of(context).pop();
Navigator.of(context).pop();
Navigator.of(context).pushNamed(
'/patient-access-review',
arguments: widget.signedInUser,
);
String message = "";
if (accessType == "approved") {
message =
"You've successfully approved the access request! ${widget.accessRequests[index].Name} now has access to your profile until ${widget.accessRequests[index].revoke_date.substring(0, 16).replaceAll("T", " ")}.";
} else {
message =
"You've declined the access request. ${widget.accessRequests[index].Name} will not have access to your profile.";
}
successPopUp(message);
} else {
internetConnectionPopUp();
}
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
void successPopUp(String message) {
showDialog(
context: context,
builder: (context) {
return MIHSuccessMessage(
successType: "Success",
successMessage: message,
);
},
);
}
void accessCancelledWarning() {
showDialog(
context: context,
builder: (context) {
return const MIHWarningMessage(warningType: "Access Cancelled");
},
);
}
Widget displayQueue(int index) {
String line1 =
"Appointment: ${widget.accessRequests[index].date_time.substring(0, 16).replaceAll("T", " ")}";
String line2 = "";
line2 += "Requestor: ${widget.accessRequests[index].Name}\n";
//subtitle += "Business Type: ${widget.accessRequests[index].type}\n";
String line3 = "Access: ";
String access = "";
var nowDate = DateTime.now();
var expireyDate = DateTime.parse(widget.accessRequests[index].revoke_date);
if (expireyDate.isBefore(nowDate)) {
access += "EXPIRED";
} else {
access += "${widget.accessRequests[index].access.toUpperCase()}";
}
String line4 = "";
if (widget.accessRequests[index].revoke_date.contains("9999")) {
line4 += "Access Expiration date: NOT SET";
} else {
line4 +=
"Access Expiration date: ${widget.accessRequests[index].revoke_date.substring(0, 10)}";
}
TextSpan accessWithColour;
if (access == "APPROVED") {
accessWithColour = TextSpan(
text: "$access\n",
style: TextStyle(
color: MzanziInnovationHub.of(context)!.theme.successColor()));
} else if (access == "PENDING") {
accessWithColour = TextSpan(
text: "$access\n",
style: TextStyle(
color:
MzanziInnovationHub.of(context)!.theme.messageTextColor()));
} else {
accessWithColour = TextSpan(
text: "$access\n",
style: TextStyle(
color: MzanziInnovationHub.of(context)!.theme.errorColor()));
}
return ListTile(
title: Text(
line1,
style: TextStyle(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
),
subtitle: RichText(
text: TextSpan(
text: line2,
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
TextSpan(text: line3),
accessWithColour,
TextSpan(text: line4),
]),
),
// Text(
// subtitle,
// style: TextStyle(
// color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
// ),
// ),
onTap: () {
if (access == "CANCELLED") {
accessCancelledWarning();
} else {
viewApprovalPopUp(index);
}
},
// trailing: Icon(
// Icons.arrow_forward,
// color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
// ),
);
}
void checkScreenSize() {
if (MzanziInnovationHub.of(context)!.theme.screenType == "desktop") {
setState(() {
popUpWidth = (width / 4) * 2;
popUpheight = null;
popUpButtonWidth = 300;
popUpTitleSize = 25.0;
popUpSubtitleSize = 20.0;
popUpBodySize = 15;
popUpPaddingSize = 25.0;
popUpIconSize = 100;
});
} else {
setState(() {
popUpWidth = width - (width * 0.1);
popUpheight = null;
popUpButtonWidth = 300;
popUpTitleSize = 20.0;
popUpSubtitleSize = 18.0;
popUpBodySize = 15;
popUpPaddingSize = 15.0;
popUpIconSize = 100;
});
}
}
void viewApprovalPopUp(int index) {
String subtitle =
"Appointment: ${widget.accessRequests[index].date_time.substring(0, 16).replaceAll("T", " ")}\n";
subtitle += "Requestor: ${widget.accessRequests[index].Name}\n";
subtitle += "Business Type: ${widget.accessRequests[index].type}\n\n";
subtitle +=
"You are about to approve an access request to your patient profile.\nPlease be aware that once approved, ${widget.accessRequests[index].Name} will have access to your profile information until ${widget.accessRequests[index].revoke_date.substring(0, 16).replaceAll("T", " ")}.\nIf you are unsure about an upcoming appointment with ${widget.accessRequests[index].Name}, please contact ${widget.accessRequests[index].contact_no} for clarification before approving this request.\n";
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MIHWindow(
fullscreen: false,
windowTitle: "Update Appointment Access",
windowBody: [
const SizedBox(
height: 10,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Text(
subtitle,
textAlign: TextAlign.left,
style: TextStyle(
color:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
fontSize: popUpBodySize,
//fontWeight: FontWeight.bold,
),
),
),
Wrap(
runSpacing: 10,
spacing: 10,
children: [
SizedBox(
width: popUpButtonWidth,
height: 50,
child: MIHButton(
onTap: () {
updateAccessAPICall(index, "declined");
},
buttonText: "Decline",
buttonColor:
MzanziInnovationHub.of(context)!.theme.errorColor(),
textColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
),
),
SizedBox(
width: popUpButtonWidth,
height: 50,
child: MIHButton(
onTap: () {
updateAccessAPICall(index, "approved");
},
buttonText: "Approve",
buttonColor:
MzanziInnovationHub.of(context)!.theme.successColor(),
textColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
),
),
],
),
const SizedBox(
height: 10,
),
],
windowTools: const [],
onWindowTapClose: () {
Navigator.pop(context);
}),
);
// showDialog(
// context: context,
// barrierDismissible: false,
// builder: (context) => Dialog(
// child: Stack(
// children: [
// Container(
// //padding: const EdgeInsets.all(15.0),
// width: popUpWidth,
// height: popUpheight,
// decoration: BoxDecoration(
// color: MzanziInnovationHub.of(context)!.theme.primaryColor(),
// borderRadius: BorderRadius.circular(25.0),
// border: Border.all(
// color:
// MzanziInnovationHub.of(context)!.theme.secondaryColor(),
// width: 5.0),
// ),
// child: SingleChildScrollView(
// padding: EdgeInsets.all(popUpPaddingSize),
// child: Column(
// mainAxisSize: MainAxisSize.min,
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// Text(
// "Update Appointment Access",
// textAlign: TextAlign.center,
// style: TextStyle(
// color: MzanziInnovationHub.of(context)!
// .theme
// .secondaryColor(),
// fontSize: popUpTitleSize,
// fontWeight: FontWeight.bold,
// ),
// ),
// const SizedBox(height: 15.0),
// Text(
// subtitle,
// textAlign: TextAlign.left,
// style: TextStyle(
// color: MzanziInnovationHub.of(context)!
// .theme
// .secondaryColor(),
// fontSize: popUpBodySize,
// //fontWeight: FontWeight.bold,
// ),
// ),
// const SizedBox(height: 10.0),
// Wrap(
// runSpacing: 10,
// spacing: 10,
// children: [
// SizedBox(
// width: popUpButtonWidth,
// height: 50,
// child: MIHButton(
// onTap: () {
// updateAccessAPICall(index, "declined");
// },
// buttonText: "Decline",
// buttonColor: MzanziInnovationHub.of(context)!
// .theme
// .errorColor(),
// textColor: MzanziInnovationHub.of(context)!
// .theme
// .primaryColor(),
// ),
// ),
// SizedBox(
// width: popUpButtonWidth,
// height: 50,
// child: MIHButton(
// onTap: () {
// updateAccessAPICall(index, "approved");
// },
// buttonText: "Approve",
// buttonColor: MzanziInnovationHub.of(context)!
// .theme
// .successColor(),
// textColor: MzanziInnovationHub.of(context)!
// .theme
// .primaryColor(),
// ),
// ),
// ],
// )
// ],
// ),
// ),
// ),
// Positioned(
// top: 5,
// right: 5,
// width: 50,
// height: 50,
// child: IconButton(
// onPressed: () {
// Navigator.pop(context);
// },
// icon: Icon(
// Icons.close,
// color: MzanziInnovationHub.of(context)!.theme.errorColor(),
// size: 35,
// ),
// ),
// ),
// ],
// ),
// ),
// );
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
setState(() {
width = size.width;
height = size.height;
});
checkScreenSize();
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
);
},
itemCount: widget.accessRequests.length,
itemBuilder: (context, index) {
//final patient = widget.patients[index].id_no.contains(widget.searchString);
//print(index);
return displayQueue(index);
},
);
}
}

View File

@@ -0,0 +1,136 @@
import 'package:flutter/material.dart';
import '../../../main.dart';
import '../../../mih_components/mih_pop_up_messages/mih_warning_message.dart';
import '../../../mih_env/env.dart';
import '../../../mih_objects/app_user.dart';
import '../../../mih_objects/patient_queue.dart';
class BuildAppointmentList extends StatefulWidget {
final List<PatientQueue> patientQueue;
final AppUser signedInUser;
const BuildAppointmentList({
super.key,
required this.patientQueue,
required this.signedInUser,
});
@override
State<BuildAppointmentList> createState() => _BuildPatientsListState();
}
class _BuildPatientsListState extends State<BuildAppointmentList> {
String baseAPI = AppEnviroment.baseApiUrl;
TextEditingController dateController = TextEditingController();
TextEditingController timeController = TextEditingController();
TextEditingController idController = TextEditingController();
TextEditingController fnameController = TextEditingController();
TextEditingController lnameController = TextEditingController();
TextEditingController daysExtensionController = TextEditingController();
int counter = 0;
Widget displayQueue(int index) {
String title = widget.patientQueue[index].business_name.toUpperCase();
// widget.patientQueue[index].date_time.split('T')[1].substring(0, 5);
String line234 = "";
// var nowDate = DateTime.now();
// var expireyDate = DateTime.parse(widget.patientQueue[index].revoke_date);
line234 +=
widget.patientQueue[index].date_time.split('T')[1].substring(0, 5);
return ListTile(
title: Text(
title,
style: TextStyle(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
),
subtitle: RichText(
text: TextSpan(
text: "Time: $line234",
style: DefaultTextStyle.of(context).style,
// children: [
// TextSpan(text: line5),
// accessWithColour,
// TextSpan(text: line6),
// ]
),
),
onTap: () {},
);
}
bool isAccessExpired(String accessType) {
if (accessType == "EXPIRED") {
return true;
} else {
return false;
}
}
void noAccessWarning() {
showDialog(
context: context,
builder: (context) {
return const MIHWarningMessage(warningType: "No Access");
},
);
}
void accessDeclinedWarning() {
showDialog(
context: context,
builder: (context) {
return const MIHWarningMessage(warningType: "Access Declined");
},
);
}
void appointmentCancelledWarning() {
showDialog(
context: context,
builder: (context) {
return const MIHWarningMessage(warningType: "Appointment Canelled");
},
);
}
void expiredAccessWarning() {
showDialog(
context: context,
builder: (context) {
return const MIHWarningMessage(warningType: "Expired Access");
},
);
}
@override
void dispose() {
daysExtensionController.dispose();
dateController.dispose();
timeController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListView.separated(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
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);
},
);
}
}