filename components and MIH_Package to mih_package
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||
import 'package:patient_manager/env/env.dart';
|
||||
import 'package:patient_manager/main.dart';
|
||||
import 'package:patient_manager/objects/arguments.dart';
|
||||
import 'package:patient_manager/objects/patients.dart';
|
||||
import 'package:patient_manager/mih_packages/patient_profile/patientAdd.dart';
|
||||
import 'package:patient_manager/mih_packages/patient_profile/patientView.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
|
||||
class AddOrViewPatient extends StatefulWidget {
|
||||
//final AppUser signedInUser;
|
||||
final PatientViewArguments arguments;
|
||||
const AddOrViewPatient({
|
||||
super.key,
|
||||
required this.arguments,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AddOrViewPatient> createState() => _AddOrViewPatientState();
|
||||
}
|
||||
|
||||
class _AddOrViewPatientState extends State<AddOrViewPatient> {
|
||||
late double width;
|
||||
late double height;
|
||||
late Widget loading;
|
||||
|
||||
Future<Patient?> fetchPatient() async {
|
||||
//print("Patien manager page: $endpoint");
|
||||
final response = await http.get(Uri.parse(
|
||||
"${AppEnviroment.baseApiUrl}/patients/${widget.arguments.signedInUser.app_id}"));
|
||||
// print("Here");
|
||||
// print("Body: ${response.body}");
|
||||
// print("Code: ${response.statusCode}");
|
||||
// var errorCode = response.statusCode.toString();
|
||||
// var errorBody = response.body;
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
// print("Here1");
|
||||
var decodedData = jsonDecode(response.body);
|
||||
// print("Here2");
|
||||
Patient patients = Patient.fromJson(decodedData as Map<String, dynamic>);
|
||||
// print("Here3");
|
||||
// print(patients);
|
||||
return patients;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
setState(() {
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
});
|
||||
return FutureBuilder(
|
||||
future: fetchPatient(),
|
||||
builder: (ctx, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.hasData) {
|
||||
// Extracting data from snapshot object
|
||||
//final data = snapshot.data as String;
|
||||
return PatientView(
|
||||
arguments: PatientViewArguments(
|
||||
widget.arguments.signedInUser,
|
||||
snapshot.requireData,
|
||||
null,
|
||||
null,
|
||||
widget.arguments.type,
|
||||
));
|
||||
} else if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
loading = Container(
|
||||
width: width,
|
||||
height: height,
|
||||
color: MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
child: const Mihloadingcircle(),
|
||||
);
|
||||
|
||||
return loading;
|
||||
} else {
|
||||
return AddPatient(signedInUser: widget.arguments.signedInUser);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/main.dart';
|
||||
import 'package:patient_manager/objects/arguments.dart';
|
||||
import 'package:syncfusion_flutter_core/theme.dart';
|
||||
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
|
||||
|
||||
class BuildFileView extends StatefulWidget {
|
||||
final String link;
|
||||
final String path;
|
||||
const BuildFileView({
|
||||
super.key,
|
||||
required this.link,
|
||||
required this.path,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildFileView> createState() => _BuildFileViewState();
|
||||
}
|
||||
|
||||
class _BuildFileViewState extends State<BuildFileView> {
|
||||
late PdfViewerController pdfViewerController = PdfViewerController();
|
||||
//late TextEditingController currentPageController = TextEditingController();
|
||||
double startZoomLevel = 1;
|
||||
|
||||
String getExtType(String path) {
|
||||
//print(pdfLink.split(".")[1]);
|
||||
return path.split(".").last;
|
||||
}
|
||||
|
||||
String getFileName(String path) {
|
||||
//print(pdfLink.split(".")[1]);
|
||||
return path.split("/").last;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
pdfViewerController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// double width = MediaQuery.sizeOf(context).width;
|
||||
// double height = MediaQuery.sizeOf(context).height;
|
||||
if (getExtType(widget.path).toLowerCase() == "pdf") {
|
||||
//print(widget.pdfLink);
|
||||
return Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SfPdfViewerTheme(
|
||||
data: SfPdfViewerThemeData(
|
||||
backgroundColor:
|
||||
MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
),
|
||||
child: SfPdfViewer.network(
|
||||
widget.link,
|
||||
controller: pdfViewerController,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
right: 5,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton.filled(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(
|
||||
'/file-veiwer',
|
||||
arguments: FileViewArguments(
|
||||
widget.link,
|
||||
widget.path,
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.fullscreen,
|
||||
color: MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: InteractiveViewer(
|
||||
maxScale: 5.0,
|
||||
//minScale: 0.,
|
||||
child: Image.network(widget.link),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
right: 5,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton.filled(
|
||||
onPressed: () {
|
||||
//expandImage(width, height);
|
||||
Navigator.of(context).pushNamed(
|
||||
'/file-veiwer',
|
||||
arguments: FileViewArguments(
|
||||
widget.link,
|
||||
widget.path,
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.fullscreen,
|
||||
color: MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/mih_packages/patient_profile/builder/BuildFileView.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_delete_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_error_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_success_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_button.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/business.dart';
|
||||
import 'package:patient_manager/objects/businessUser.dart';
|
||||
import 'package:patient_manager/objects/files.dart';
|
||||
import 'package:patient_manager/objects/patients.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
import "package:universal_html/html.dart" as html;
|
||||
|
||||
class BuildFilesList extends StatefulWidget {
|
||||
final AppUser signedInUser;
|
||||
final List<PFile> files;
|
||||
final Patient selectedPatient;
|
||||
final Business? business;
|
||||
final BusinessUser? businessUser;
|
||||
|
||||
const BuildFilesList({
|
||||
super.key,
|
||||
required this.files,
|
||||
required this.signedInUser,
|
||||
required this.selectedPatient,
|
||||
required this.business,
|
||||
required this.businessUser,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildFilesList> createState() => _BuildFilesListState();
|
||||
}
|
||||
|
||||
class _BuildFilesListState extends State<BuildFilesList> {
|
||||
int indexOn = 0;
|
||||
final baseAPI = AppEnviroment.baseApiUrl;
|
||||
final basefile = AppEnviroment.baseFileUrl;
|
||||
String fileUrl = "";
|
||||
|
||||
Future<String> getFileUrlApiCall(String filePath) async {
|
||||
var url = "$baseAPI/minio/pull/file/${AppEnviroment.getEnv()}/$filePath";
|
||||
//print(url);
|
||||
var response = await http.get(Uri.parse(url));
|
||||
// print("here1");
|
||||
//print(response.statusCode);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
//print("here2");
|
||||
String body = response.body;
|
||||
//print(body);
|
||||
//print("here3");
|
||||
var decodedData = jsonDecode(body);
|
||||
//print("Dedoced: ${decodedData['minioURL']}");
|
||||
|
||||
return decodedData['minioURL'];
|
||||
//AppUser u = AppUser.fromJson(decodedData);
|
||||
// print(u.email);
|
||||
//return "AlometThere";
|
||||
} else {
|
||||
throw Exception("Error: GetUserData status code ${response.statusCode}");
|
||||
}
|
||||
|
||||
//print(url);
|
||||
// var response = await http.get(Uri.parse(url));
|
||||
// // print("here1");
|
||||
// //print(response.statusCode);
|
||||
|
||||
// if (response.statusCode == 200) {
|
||||
// //print("here2");
|
||||
// String body = response.body;
|
||||
// //print(body);
|
||||
// //print("here3");
|
||||
// var decodedData = jsonDecode(body);
|
||||
// //print("Dedoced: ${decodedData['minioURL']}");
|
||||
|
||||
// return decodedData['minioURL'];
|
||||
// //AppUser u = AppUser.fromJson(decodedData);
|
||||
// // print(u.email);
|
||||
// //return "AlometThere";
|
||||
// } else {
|
||||
// throw Exception("Error: GetUserData status code ${response.statusCode}");
|
||||
// }
|
||||
}
|
||||
|
||||
Future<void> deleteFileApiCall(String filePath, int fileID) async {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
// delete file from minio
|
||||
var response = await http.delete(
|
||||
Uri.parse("$baseAPI/minio/delete/file/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{"file_path": filePath}),
|
||||
);
|
||||
//print("Here4");
|
||||
//print(response.statusCode);
|
||||
if (response.statusCode == 200) {
|
||||
//SQL delete
|
||||
var response2 = await http.delete(
|
||||
Uri.parse("$baseAPI/files/delete/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{"idpatient_files": fileID}),
|
||||
);
|
||||
if (response2.statusCode == 200) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
//print(widget.business);
|
||||
if (widget.business == null) {
|
||||
Navigator.of(context).pushNamed('/patient-manager/patient',
|
||||
arguments: PatientViewArguments(
|
||||
widget.signedInUser,
|
||||
widget.selectedPatient,
|
||||
widget.businessUser,
|
||||
widget.business,
|
||||
"personal"));
|
||||
} else {
|
||||
Navigator.of(context).pushNamed('/patient-manager/patient',
|
||||
arguments: PatientViewArguments(
|
||||
widget.signedInUser,
|
||||
widget.selectedPatient,
|
||||
widget.businessUser,
|
||||
widget.business,
|
||||
"business"));
|
||||
}
|
||||
|
||||
// Navigator.of(context)
|
||||
// .pushNamed('/patient-profile', arguments: widget.signedInUser);
|
||||
// setState(() {});
|
||||
String message =
|
||||
"The File has been deleted successfully. This means it will no longer be visible on your and cannot be used for future appointments.";
|
||||
successPopUp(message);
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
}
|
||||
|
||||
void internetConnectionPopUp() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Internet Connection");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void successPopUp(String message) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MIHSuccessMessage(
|
||||
successType: "Success",
|
||||
successMessage: message,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void deleteFilePopUp(String filePath, int fileID) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MIHDeleteMessage(
|
||||
deleteType: "File",
|
||||
onTap: () async {
|
||||
await deleteFileApiCall(filePath, fileID);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void viewFilePopUp(String fileName, String filePath, int fileID, String url) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => Dialog(
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
width: 800.0,
|
||||
//height: 475.0,
|
||||
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: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 25,
|
||||
),
|
||||
Text(
|
||||
fileName,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
fontSize: 35.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25.0),
|
||||
Expanded(
|
||||
child: BuildFileView(
|
||||
link: url,
|
||||
path: filePath,
|
||||
//pdfLink: '${AppEnviroment.baseFileUrl}/mih/$filePath',
|
||||
)),
|
||||
const SizedBox(height: 30.0),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
height: 50,
|
||||
child: MIHButton(
|
||||
onTap: () {
|
||||
html.window.open(
|
||||
url,
|
||||
// '${AppEnviroment.baseFileUrl}/mih/$filePath',
|
||||
'download');
|
||||
},
|
||||
buttonText: "Dowload",
|
||||
buttonColor: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
left: 5,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
deleteFilePopUp(filePath, fileID);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.delete,
|
||||
color:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.files.isNotEmpty) {
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return Divider(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
);
|
||||
},
|
||||
itemCount: widget.files.length,
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
title: Text(
|
||||
widget.files[index].file_name,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
widget.files[index].insert_date,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
trailing: Icon(
|
||||
Icons.arrow_forward,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
onTap: () async {
|
||||
await getFileUrlApiCall(widget.files[index].file_path)
|
||||
.then((urlHere) {
|
||||
//print(url);
|
||||
setState(() {
|
||||
fileUrl = urlHere;
|
||||
});
|
||||
});
|
||||
|
||||
viewFilePopUp(
|
||||
widget.files[index].file_name,
|
||||
widget.files[index].file_path,
|
||||
widget.files[index].idpatient_files,
|
||||
fileUrl);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return const Center(
|
||||
child: Text(
|
||||
"No Documents Available",
|
||||
style: TextStyle(fontSize: 25, color: Colors.grey),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/main.dart';
|
||||
import 'package:patient_manager/objects/medicine.dart';
|
||||
|
||||
class BuildMedicinesList extends StatefulWidget {
|
||||
final TextEditingController contoller;
|
||||
final List<Medicine> medicines;
|
||||
//final searchString;
|
||||
|
||||
const BuildMedicinesList({
|
||||
super.key,
|
||||
required this.contoller,
|
||||
required this.medicines,
|
||||
//required this.searchString,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildMedicinesList> createState() => _BuildMedicinesListState();
|
||||
}
|
||||
|
||||
class _BuildMedicinesListState extends State<BuildMedicinesList> {
|
||||
int indexOn = 0;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.separated(
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return Divider(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
);
|
||||
},
|
||||
itemCount: widget.medicines.length,
|
||||
itemBuilder: (context, index) {
|
||||
//final patient = widget.patients[index].id_no.contains(widget.searchString);
|
||||
return ListTile(
|
||||
title: Text(
|
||||
widget.medicines[index].name,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
"${widget.medicines[index].unit} - ${widget.medicines[index].form}",
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
widget.contoller.text =
|
||||
"${widget.medicines[index].name}%t${widget.medicines[index].unit}%t${widget.medicines[index].form}";
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
},
|
||||
trailing: Icon(
|
||||
Icons.arrow_forward,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_text_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_delete_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_error_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_multiline_text_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_success_message.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/business.dart';
|
||||
import 'package:patient_manager/objects/businessUser.dart';
|
||||
//import 'package:patient_manager/MIH_Components/mybutton.dart';
|
||||
import 'package:patient_manager/objects/notes.dart';
|
||||
import 'package:patient_manager/objects/patients.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
|
||||
class BuildNotesList extends StatefulWidget {
|
||||
final AppUser signedInUser;
|
||||
final List<Note> notes;
|
||||
final Patient selectedPatient;
|
||||
final Business? business;
|
||||
final BusinessUser? businessUser;
|
||||
const BuildNotesList({
|
||||
super.key,
|
||||
required this.notes,
|
||||
required this.signedInUser,
|
||||
required this.selectedPatient,
|
||||
required this.business,
|
||||
required this.businessUser,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildNotesList> createState() => _BuildNotesListState();
|
||||
}
|
||||
|
||||
class _BuildNotesListState extends State<BuildNotesList> {
|
||||
final noteTitleController = TextEditingController();
|
||||
final noteTextController = TextEditingController();
|
||||
final businessNameController = TextEditingController();
|
||||
final userNameController = TextEditingController();
|
||||
final dateController = TextEditingController();
|
||||
int indexOn = 0;
|
||||
final baseAPI = AppEnviroment.baseApiUrl;
|
||||
|
||||
Future<void> deleteNoteApiCall(int NoteId) async {
|
||||
var response = await http.delete(
|
||||
Uri.parse("$baseAPI/notes/delete/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{"idpatient_notes": NoteId}),
|
||||
);
|
||||
//print("Here4");
|
||||
//print(response.statusCode);
|
||||
if (response.statusCode == 200) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
if (widget.business == null) {
|
||||
Navigator.of(context).pushNamed('/patient-manager/patient',
|
||||
arguments: PatientViewArguments(
|
||||
widget.signedInUser,
|
||||
widget.selectedPatient,
|
||||
widget.businessUser,
|
||||
widget.business,
|
||||
"personal"));
|
||||
} else {
|
||||
Navigator.of(context).pushNamed('/patient-manager/patient',
|
||||
arguments: PatientViewArguments(
|
||||
widget.signedInUser,
|
||||
widget.selectedPatient,
|
||||
widget.businessUser,
|
||||
widget.business,
|
||||
"business"));
|
||||
}
|
||||
setState(() {});
|
||||
String message =
|
||||
"The note has been deleted successfully. This means it will no longer be visible on your and cannot be used for future appointments.";
|
||||
successPopUp(message);
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
}
|
||||
|
||||
void internetConnectionPopUp() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Internet Connection");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void successPopUp(String message) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MIHSuccessMessage(
|
||||
successType: "Success",
|
||||
successMessage: message,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void deletePatientPopUp(int NoteId) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MIHDeleteMessage(
|
||||
deleteType: "Note",
|
||||
onTap: () {
|
||||
deleteNoteApiCall(NoteId);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void viewNotePopUp(Note selectednote) {
|
||||
setState(() {
|
||||
noteTitleController.text = selectednote.note_name;
|
||||
noteTextController.text = selectednote.note_text;
|
||||
businessNameController.text = selectednote.doc_office;
|
||||
userNameController.text = selectednote.doctor;
|
||||
dateController.text = selectednote.insert_date;
|
||||
});
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => Dialog(
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
width: 700.0,
|
||||
//height: 475.0,
|
||||
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: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 25,
|
||||
),
|
||||
Text(
|
||||
selectednote.note_name,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
fontSize: 35.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25.0),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: MIHTextField(
|
||||
controller: businessNameController,
|
||||
hintText: "Office",
|
||||
editable: false,
|
||||
required: false,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: MIHTextField(
|
||||
controller: userNameController,
|
||||
hintText: "Created By",
|
||||
editable: false,
|
||||
required: false,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: MIHTextField(
|
||||
controller: dateController,
|
||||
hintText: "Created Date",
|
||||
editable: false,
|
||||
required: false,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: MIHTextField(
|
||||
controller: noteTitleController,
|
||||
hintText: "Note Title",
|
||||
editable: false,
|
||||
required: false,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
Expanded(
|
||||
child: MIHMLTextField(
|
||||
controller: noteTextController,
|
||||
hintText: "Note Details",
|
||||
editable: false,
|
||||
required: false,
|
||||
),
|
||||
),
|
||||
//const SizedBox(height: 25.0),
|
||||
// SizedBox(
|
||||
// width: 300,
|
||||
// height: 100,
|
||||
// child: MIHButton(
|
||||
// onTap: () {
|
||||
// Navigator.pop(context);
|
||||
// },
|
||||
// buttonText: "Close",
|
||||
// buttonColor: Colors.blueAccent,
|
||||
// textColor: Colors.white,
|
||||
// ),
|
||||
// )
|
||||
],
|
||||
),
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
left: 5,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
deletePatientPopUp(selectednote.idpatient_notes);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.delete,
|
||||
color:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
noteTextController.dispose();
|
||||
businessNameController.dispose();
|
||||
userNameController.dispose();
|
||||
dateController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.notes.isNotEmpty) {
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return Divider(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
);
|
||||
},
|
||||
itemCount: widget.notes.length,
|
||||
itemBuilder: (context, index) {
|
||||
String notePreview = widget.notes[index].note_text;
|
||||
if (notePreview.length > 30) {
|
||||
notePreview = "${notePreview.substring(0, 30)} ...";
|
||||
}
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"${widget.notes[index].note_name}\n${widget.notes[index].doc_office} - ${widget.notes[index].doctor}",
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
"${widget.notes[index].insert_date}:\n$notePreview",
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
), //Text(widget.notes[index].note_text),
|
||||
trailing: Icon(
|
||||
Icons.arrow_forward,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
onTap: () {
|
||||
viewNotePopUp(widget.notes[index]);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return const Center(
|
||||
child: Text(
|
||||
"No Notes Available",
|
||||
style: TextStyle(fontSize: 25, color: Colors.grey),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_date_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_text_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_time_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_error_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_button.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_success_message.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/business.dart';
|
||||
import 'package:patient_manager/objects/patients.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
|
||||
class BuildPatientsList extends StatefulWidget {
|
||||
final List<Patient> patients;
|
||||
final AppUser signedInUser;
|
||||
final Business? business;
|
||||
final BusinessArguments arguments;
|
||||
|
||||
const BuildPatientsList({
|
||||
super.key,
|
||||
required this.patients,
|
||||
required this.signedInUser,
|
||||
required this.business,
|
||||
required this.arguments,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildPatientsList> createState() => _BuildPatientsListState();
|
||||
}
|
||||
|
||||
class _BuildPatientsListState extends State<BuildPatientsList> {
|
||||
TextEditingController dateController = TextEditingController();
|
||||
TextEditingController timeController = TextEditingController();
|
||||
TextEditingController idController = TextEditingController();
|
||||
TextEditingController fnameController = TextEditingController();
|
||||
TextEditingController lnameController = TextEditingController();
|
||||
|
||||
final baseAPI = AppEnviroment.baseApiUrl;
|
||||
|
||||
Future<void> addPatientAppointmentAPICall(int index) async {
|
||||
var response = await http.post(
|
||||
Uri.parse("$baseAPI/queue/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.arguments.signedInUser,
|
||||
widget.arguments.businessUser,
|
||||
widget.arguments.business,
|
||||
),
|
||||
);
|
||||
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 submitApointment(int index) {
|
||||
addPatientAppointmentAPICall(index);
|
||||
}
|
||||
|
||||
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) => Dialog(
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
width: 700.0,
|
||||
//height: 475.0,
|
||||
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: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"Patient Appointment",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
fontSize: 35.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25.0),
|
||||
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");
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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: () {
|
||||
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: () {
|
||||
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();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.separated(
|
||||
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);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_warning_message.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/business.dart';
|
||||
import 'package:patient_manager/objects/businessUser.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> patientQueue;
|
||||
final AppUser signedInUser;
|
||||
final Business? business;
|
||||
final BusinessUser? businessUser;
|
||||
|
||||
const BuildPatientQueueList({
|
||||
super.key,
|
||||
required this.patientQueue,
|
||||
required this.signedInUser,
|
||||
required this.business,
|
||||
required this.businessUser,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildPatientQueueList> createState() => _BuildPatientsListState();
|
||||
}
|
||||
|
||||
class _BuildPatientsListState extends State<BuildPatientQueueList> {
|
||||
String baseAPI = AppEnviroment.baseApiUrl;
|
||||
|
||||
Future<Patient> 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 fname = widget.patientQueue[index].first_name[0] + "********";
|
||||
String lname = widget.patientQueue[index].last_name[0] + "********";
|
||||
String title =
|
||||
widget.patientQueue[index].date_time.split('T')[1].substring(0, 5);
|
||||
String subtitle = "";
|
||||
var nowDate = DateTime.now();
|
||||
var expireyDate = DateTime.parse(widget.patientQueue[index].revoke_date);
|
||||
|
||||
if (widget.patientQueue[index].access != "approved" ||
|
||||
expireyDate.isBefore(nowDate)) {
|
||||
subtitle += "Name: $fname $lname\n";
|
||||
subtitle += "ID No.: ${widget.patientQueue[index].id_no}\n";
|
||||
subtitle += "Medical Aid No: ********";
|
||||
//subtitle += "********";
|
||||
} else {
|
||||
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 +=
|
||||
// "\nMedical Aid No: ";
|
||||
subtitle += widget.patientQueue[index].medical_aid_no;
|
||||
}
|
||||
}
|
||||
if (expireyDate.isBefore(nowDate)) {
|
||||
subtitle += "\nAccess Request: EXPIRED";
|
||||
} else {
|
||||
subtitle +=
|
||||
"\nAccess Request: ${widget.patientQueue[index].access.toUpperCase()}";
|
||||
}
|
||||
|
||||
subtitle +=
|
||||
"\nAccess Expiration date: ${widget.patientQueue[index].revoke_date.substring(0, 16).replaceAll("T", " ")}";
|
||||
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: () {
|
||||
var todayDate = DateTime.now();
|
||||
var revokeDate = DateTime.parse(widget.patientQueue[index].revoke_date);
|
||||
// print(
|
||||
// "Todays: $todayDate\nRevoke Date: $revokeDate\nHas revoke date passed: ${revokeDate.isBefore(todayDate)}");
|
||||
if (revokeDate.isBefore(todayDate)) {
|
||||
expiredAccessWarning();
|
||||
} else if (widget.patientQueue[index].access != "pending") {
|
||||
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,
|
||||
widget.businessUser,
|
||||
widget.business,
|
||||
"business",
|
||||
));
|
||||
});
|
||||
},
|
||||
);
|
||||
} else {
|
||||
noAccessWarning();
|
||||
}
|
||||
},
|
||||
trailing: Icon(
|
||||
Icons.arrow_forward,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void noAccessWarning() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHWarningMessage(warningType: "No Access");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void expiredAccessWarning() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHWarningMessage(warningType: "Expired Access");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@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);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/main.dart';
|
||||
import 'package:patient_manager/objects/arguments.dart';
|
||||
import 'package:syncfusion_flutter_core/theme.dart';
|
||||
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
|
||||
import "package:universal_html/html.dart" as html;
|
||||
|
||||
class FullScreenFileViewer extends StatefulWidget {
|
||||
final FileViewArguments arguments;
|
||||
const FullScreenFileViewer({
|
||||
super.key,
|
||||
required this.arguments,
|
||||
});
|
||||
|
||||
@override
|
||||
State<FullScreenFileViewer> createState() => _FullScreenFileViewerState();
|
||||
}
|
||||
|
||||
class _FullScreenFileViewerState extends State<FullScreenFileViewer> {
|
||||
late PdfViewerController pdfViewerController = PdfViewerController();
|
||||
int currentPageCount = 0;
|
||||
int currentPage = 0;
|
||||
double startZoomLevel = 1.0;
|
||||
double zoomOut = 0;
|
||||
|
||||
String getExtType(String path) {
|
||||
//print(pdfLink.split(".")[1]);
|
||||
return path.split(".").last;
|
||||
}
|
||||
|
||||
String getFileName(String path) {
|
||||
//print(pdfLink.split(".")[1]);
|
||||
return path.split("/").last;
|
||||
}
|
||||
|
||||
void onPageSelect() {
|
||||
setState(() {
|
||||
currentPage = pdfViewerController.pageNumber;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
pdfViewerController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
pdfViewerController.addListener(onPageSelect);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
double width = size.width;
|
||||
double height = size.height;
|
||||
|
||||
if (getExtType(widget.arguments.path).toLowerCase() == "pdf") {
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
width: width,
|
||||
padding: const EdgeInsets.only(top: 20.0),
|
||||
decoration: BoxDecoration(
|
||||
color: MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
SizedBox(
|
||||
width: width - zoomOut,
|
||||
height: height - 70,
|
||||
child: SfPdfViewerTheme(
|
||||
data: SfPdfViewerThemeData(
|
||||
backgroundColor: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.primaryColor(),
|
||||
),
|
||||
child: SfPdfViewer.network(
|
||||
widget.arguments.link,
|
||||
controller: pdfViewerController,
|
||||
initialZoomLevel: startZoomLevel,
|
||||
pageSpacing: 2,
|
||||
maxZoomLevel: 5,
|
||||
interactionMode: PdfInteractionMode.pan,
|
||||
onDocumentLoaded: (details) {
|
||||
setState(() {
|
||||
currentPage = pdfViewerController.pageNumber;
|
||||
currentPageCount = pdfViewerController.pageCount;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
left: 2,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.fullscreen_exit,
|
||||
color:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
right: 2,
|
||||
//width: 50,
|
||||
height: 50,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
pdfViewerController.previousPage();
|
||||
//print(pdfViewerController.);
|
||||
//if (pdfViewerController.pageNumber > 1) {
|
||||
setState(() {
|
||||
currentPage = pdfViewerController.pageNumber;
|
||||
});
|
||||
// }
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
// SizedBox(
|
||||
// width: 40,
|
||||
// height: 40,
|
||||
// child: MIHTextField(
|
||||
// controller: cuntrController,
|
||||
// hintText: "",
|
||||
// editable: true,
|
||||
// required: false),
|
||||
// ),
|
||||
Text(
|
||||
"$currentPage / $currentPageCount",
|
||||
style: const TextStyle(fontSize: 20),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
pdfViewerController.nextPage();
|
||||
//print(pdfViewerController.pageNumber);
|
||||
//if (pdfViewerController.pageNumber < currentPageCount) {
|
||||
setState(() {
|
||||
currentPage = pdfViewerController.pageNumber;
|
||||
});
|
||||
//}
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.arrow_forward,
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
if (zoomOut > 0) {
|
||||
setState(() {
|
||||
zoomOut = zoomOut - 100;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
pdfViewerController.zoomLevel =
|
||||
startZoomLevel + 0.25;
|
||||
startZoomLevel = pdfViewerController.zoomLevel;
|
||||
});
|
||||
}
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.zoom_in,
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
if (pdfViewerController.zoomLevel > 1) {
|
||||
setState(() {
|
||||
pdfViewerController.zoomLevel =
|
||||
startZoomLevel - 0.25;
|
||||
startZoomLevel = pdfViewerController.zoomLevel;
|
||||
});
|
||||
} else {
|
||||
if (zoomOut < (width - 100)) {
|
||||
setState(() {
|
||||
zoomOut = zoomOut + 100;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.zoom_out,
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
html.window.open(
|
||||
widget.arguments.link,
|
||||
// '${AppEnviroment.baseFileUrl}/mih/$filePath',
|
||||
'download');
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.download,
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 50.0),
|
||||
width: width,
|
||||
// height: height,
|
||||
decoration: BoxDecoration(
|
||||
color: MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
//borderRadius: BorderRadius.circular(25.0),
|
||||
// border: Border.all(
|
||||
// color: MzanziInnovationHub.of(context)!.theme.errorColor(),
|
||||
// width: 5.0),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: InteractiveViewer(
|
||||
maxScale: 5.0,
|
||||
//minScale: 0.,
|
||||
child: Image.network(widget.arguments.link),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
left: 2,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.fullscreen_exit,
|
||||
color:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
right: 2,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
html.window.open(
|
||||
widget.arguments.link,
|
||||
// '${AppEnviroment.baseFileUrl}/mih/$filePath',
|
||||
'download');
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.download,
|
||||
color:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_dropdown_input.dart';
|
||||
//import 'package:patient_manager/MIH_Components/mihAppDrawer.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_error_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_success_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_text_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_button.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:supertokens_flutter/http.dart' as http;
|
||||
|
||||
class AddPatient extends StatefulWidget {
|
||||
final AppUser signedInUser;
|
||||
|
||||
const AddPatient({
|
||||
super.key,
|
||||
required this.signedInUser,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AddPatient> createState() => _AddPatientState();
|
||||
}
|
||||
|
||||
class _AddPatientState extends State<AddPatient> {
|
||||
final idController = TextEditingController();
|
||||
final fnameController = TextEditingController();
|
||||
final lnameController = TextEditingController();
|
||||
final cellController = TextEditingController();
|
||||
final emailController = TextEditingController();
|
||||
final medNoController = TextEditingController();
|
||||
final medNameController = TextEditingController();
|
||||
final medSchemeController = TextEditingController();
|
||||
final addressController = TextEditingController();
|
||||
final medAidController = TextEditingController();
|
||||
final medMainMemController = TextEditingController();
|
||||
final medAidCodeController = TextEditingController();
|
||||
|
||||
final baseAPI = AppEnviroment.baseApiUrl;
|
||||
late int futureDocOfficeId;
|
||||
late bool medRequired;
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
|
||||
bool isFieldsFilled() {
|
||||
if (medRequired) {
|
||||
if (idController.text.isEmpty ||
|
||||
fnameController.text.isEmpty ||
|
||||
lnameController.text.isEmpty ||
|
||||
cellController.text.isEmpty ||
|
||||
emailController.text.isEmpty ||
|
||||
medNoController.text.isEmpty ||
|
||||
medNameController.text.isEmpty ||
|
||||
medSchemeController.text.isEmpty ||
|
||||
addressController.text.isEmpty ||
|
||||
medAidController.text.isEmpty ||
|
||||
medMainMemController.text.isEmpty ||
|
||||
medAidCodeController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (idController.text.isEmpty ||
|
||||
fnameController.text.isEmpty ||
|
||||
lnameController.text.isEmpty ||
|
||||
cellController.text.isEmpty ||
|
||||
emailController.text.isEmpty ||
|
||||
addressController.text.isEmpty ||
|
||||
medAidController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> addPatientAPICall() async {
|
||||
var response = await http.post(
|
||||
Uri.parse("$baseAPI/patients/insert/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
"id_no": idController.text,
|
||||
"first_name": fnameController.text,
|
||||
"last_name": lnameController.text,
|
||||
"email": emailController.text,
|
||||
"cell_no": cellController.text,
|
||||
"medical_aid": medAidController.text,
|
||||
"medical_aid_main_member": medMainMemController.text,
|
||||
"medical_aid_no": medNoController.text,
|
||||
"medical_aid_code": medAidCodeController.text,
|
||||
"medical_aid_name": medNameController.text,
|
||||
"medical_aid_scheme": medSchemeController.text,
|
||||
"address": addressController.text,
|
||||
"app_id": widget.signedInUser.app_id,
|
||||
}),
|
||||
);
|
||||
if (response.statusCode == 201) {
|
||||
Navigator.of(context).popAndPushNamed('/patient-profile',
|
||||
arguments: PatientViewArguments(
|
||||
widget.signedInUser, null, null, null, "personal"));
|
||||
String message =
|
||||
"${fnameController.text} ${lnameController.text} patient profiole has been successfully added!\n";
|
||||
successPopUp(message);
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
}
|
||||
|
||||
void internetConnectionPopUp() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Internet Connection");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void messagePopUp(error) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(error),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void successPopUp(String message) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MIHSuccessMessage(
|
||||
successType: "Success",
|
||||
successMessage: message,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void isRequired() {
|
||||
//print("listerner triggered");
|
||||
if (medAidController.text == "Yes") {
|
||||
setState(() {
|
||||
medRequired = true;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
medRequired = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Widget displayForm() {
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
"Personal Details",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 25.0,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25.0),
|
||||
MIHTextField(
|
||||
controller: idController,
|
||||
hintText: "13 digit ID Number or Passport",
|
||||
editable: true,
|
||||
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: "Last Name",
|
||||
editable: false,
|
||||
required: true,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: cellController,
|
||||
hintText: "Cell Number",
|
||||
editable: true,
|
||||
required: true,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: emailController,
|
||||
hintText: "Email",
|
||||
editable: false,
|
||||
required: true,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: addressController,
|
||||
hintText: "Address",
|
||||
editable: true,
|
||||
required: true,
|
||||
),
|
||||
const SizedBox(height: 15.0),
|
||||
Text(
|
||||
"Medical Aid Details",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 25.0,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHDropdownField(
|
||||
controller: medAidController,
|
||||
hintText: "Medical Aid",
|
||||
editable: true,
|
||||
onSelect: (_) {
|
||||
isRequired();
|
||||
},
|
||||
required: true,
|
||||
dropdownOptions: const ["Yes", "No"],
|
||||
),
|
||||
Visibility(
|
||||
visible: medRequired,
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 10.0),
|
||||
MIHDropdownField(
|
||||
controller: medMainMemController,
|
||||
hintText: "Main Member",
|
||||
editable: medRequired,
|
||||
required: medRequired,
|
||||
dropdownOptions: const ["Yes", "No"],
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: medNoController,
|
||||
hintText: "Medical Aid No.",
|
||||
editable: medRequired,
|
||||
required: medRequired,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: medAidCodeController,
|
||||
hintText: "Medical Aid Code",
|
||||
editable: medRequired,
|
||||
required: medRequired,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: medNameController,
|
||||
hintText: "Medical Aid Name",
|
||||
editable: medRequired,
|
||||
required: medRequired,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: medSchemeController,
|
||||
hintText: "Medical Aid Scheme",
|
||||
editable: medRequired,
|
||||
required: medRequired,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30.0),
|
||||
SizedBox(
|
||||
width: 450.0,
|
||||
height: 50.0,
|
||||
child: MIHButton(
|
||||
onTap: () {
|
||||
submitForm();
|
||||
},
|
||||
buttonText: "Add",
|
||||
buttonColor:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
textColor: MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void submitForm() {
|
||||
if (isFieldsFilled()) {
|
||||
addPatientAPICall();
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Input Error");
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
idController.dispose();
|
||||
fnameController.dispose();
|
||||
lnameController.dispose();
|
||||
cellController.dispose();
|
||||
emailController.dispose();
|
||||
medNoController.dispose();
|
||||
medNameController.dispose();
|
||||
medSchemeController.dispose();
|
||||
addressController.dispose();
|
||||
medAidController.dispose();
|
||||
medMainMemController.dispose();
|
||||
medAidCodeController.dispose();
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
medAidController.addListener(isRequired);
|
||||
setState(() {
|
||||
fnameController.text = widget.signedInUser.fname;
|
||||
lnameController.text = widget.signedInUser.lname;
|
||||
emailController.text = widget.signedInUser.email;
|
||||
medAidController.text = "No";
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
// appBar: const MIHAppBar(
|
||||
// barTitle: "Add Patient",
|
||||
// propicFile: null,
|
||||
// ),
|
||||
//drawer: MIHAppDrawer(signedInUser: widget.signedInUser),
|
||||
body: SafeArea(
|
||||
child: Stack(
|
||||
children: [
|
||||
KeyboardListener(
|
||||
focusNode: _focusNode,
|
||||
autofocus: true,
|
||||
onKeyEvent: (event) async {
|
||||
if (event is KeyDownEvent &&
|
||||
event.logicalKey == LogicalKeyboardKey.enter) {
|
||||
submitForm();
|
||||
}
|
||||
},
|
||||
child: displayForm(),
|
||||
),
|
||||
Positioned(
|
||||
top: 10,
|
||||
left: 5,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_text_input.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/patients.dart';
|
||||
|
||||
class PatientDetails extends StatefulWidget {
|
||||
final AppUser signedInUser;
|
||||
final Patient selectedPatient;
|
||||
final String type;
|
||||
const PatientDetails({
|
||||
super.key,
|
||||
required this.signedInUser,
|
||||
required this.selectedPatient,
|
||||
required this.type,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PatientDetails> createState() => _PatientDetailsState();
|
||||
}
|
||||
|
||||
class _PatientDetailsState extends State<PatientDetails> {
|
||||
final idController = TextEditingController();
|
||||
final fnameController = TextEditingController();
|
||||
final lnameController = TextEditingController();
|
||||
final cellController = TextEditingController();
|
||||
final emailController = TextEditingController();
|
||||
final medNoController = TextEditingController();
|
||||
final medNameController = TextEditingController();
|
||||
final medSchemeController = TextEditingController();
|
||||
final addressController = TextEditingController();
|
||||
final medAidController = TextEditingController();
|
||||
final medMainMemController = TextEditingController();
|
||||
final medAidCodeController = TextEditingController();
|
||||
double? headingFontSize = 35.0;
|
||||
double? bodyFonstSize = 20.0;
|
||||
double textFieldWidth = 400.0;
|
||||
late String medAid;
|
||||
|
||||
Widget getPatientDetailsField() {
|
||||
return Wrap(
|
||||
spacing: 15,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: idController,
|
||||
hintText: "ID No.",
|
||||
editable: false,
|
||||
required: false),
|
||||
),
|
||||
SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: fnameController,
|
||||
hintText: "Name",
|
||||
editable: false,
|
||||
required: false),
|
||||
),
|
||||
SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: lnameController,
|
||||
hintText: "Surname",
|
||||
editable: false,
|
||||
required: false),
|
||||
),
|
||||
SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: cellController,
|
||||
hintText: "Cell No.",
|
||||
editable: false,
|
||||
required: false),
|
||||
),
|
||||
SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: emailController,
|
||||
hintText: "Email",
|
||||
editable: false,
|
||||
required: false),
|
||||
),
|
||||
SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: addressController,
|
||||
hintText: "Address",
|
||||
editable: false,
|
||||
required: false),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget getMedAidDetailsFields() {
|
||||
List<Widget> medAidDet = [];
|
||||
medAidDet.add(SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: medAidController,
|
||||
hintText: "Medical Aid",
|
||||
editable: false,
|
||||
required: false),
|
||||
));
|
||||
bool req;
|
||||
if (medAid == "Yes") {
|
||||
req = true;
|
||||
} else {
|
||||
req = false;
|
||||
}
|
||||
medAidDet.addAll([
|
||||
Visibility(
|
||||
visible: req,
|
||||
child: SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: medMainMemController,
|
||||
hintText: "Main Member",
|
||||
editable: false,
|
||||
required: false),
|
||||
),
|
||||
),
|
||||
//const SizedBox(height: 10.0),
|
||||
Visibility(
|
||||
visible: req,
|
||||
child: SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: medNoController,
|
||||
hintText: "No.",
|
||||
editable: false,
|
||||
required: false),
|
||||
),
|
||||
),
|
||||
//const SizedBox(height: 10.0),
|
||||
Visibility(
|
||||
visible: req,
|
||||
child: SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: medAidCodeController,
|
||||
hintText: "Code",
|
||||
editable: false,
|
||||
required: false),
|
||||
),
|
||||
),
|
||||
//const SizedBox(height: 10.0),
|
||||
Visibility(
|
||||
visible: req,
|
||||
child: SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: medNameController,
|
||||
hintText: "Name",
|
||||
editable: false,
|
||||
required: false),
|
||||
),
|
||||
),
|
||||
//const SizedBox(height: 10.0),
|
||||
Visibility(
|
||||
visible: req,
|
||||
child: SizedBox(
|
||||
width: textFieldWidth,
|
||||
child: MIHTextField(
|
||||
controller: medSchemeController,
|
||||
hintText: "Scheme",
|
||||
editable: false,
|
||||
required: false),
|
||||
),
|
||||
),
|
||||
//),
|
||||
]);
|
||||
|
||||
return Wrap(
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: medAidDet,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> setIcons() {
|
||||
if (widget.type == "personal") {
|
||||
return [
|
||||
Text(
|
||||
"Personal Details",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.edit),
|
||||
alignment: Alignment.topRight,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed('/patient-profile/edit',
|
||||
arguments: PatientEditArguments(
|
||||
widget.signedInUser, widget.selectedPatient));
|
||||
},
|
||||
)
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
Text(
|
||||
"Patient Details",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
idController.dispose();
|
||||
fnameController.dispose();
|
||||
lnameController.dispose();
|
||||
cellController.dispose();
|
||||
emailController.dispose();
|
||||
medNameController.dispose();
|
||||
medNoController.dispose();
|
||||
medSchemeController.dispose();
|
||||
addressController.dispose();
|
||||
medAidController.dispose();
|
||||
medMainMemController.dispose();
|
||||
medAidCodeController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
setState(() {
|
||||
idController.value = TextEditingValue(text: widget.selectedPatient.id_no);
|
||||
fnameController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.first_name);
|
||||
lnameController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.last_name);
|
||||
cellController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.cell_no);
|
||||
emailController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.email);
|
||||
medNameController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.medical_aid_name);
|
||||
medNoController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.medical_aid_no);
|
||||
medSchemeController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.medical_aid_scheme);
|
||||
addressController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.address);
|
||||
medAidController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.medical_aid);
|
||||
medMainMemController.value = TextEditingValue(
|
||||
text: widget.selectedPatient.medical_aid_main_member);
|
||||
medAidCodeController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.medical_aid_code);
|
||||
medAid = widget.selectedPatient.medical_aid;
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SelectionArea(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
//crossAxisAlignment: ,
|
||||
children: setIcons(),
|
||||
),
|
||||
Divider(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
|
||||
const SizedBox(height: 10),
|
||||
getPatientDetailsField(),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Medical Aid Details",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
Divider(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
|
||||
const SizedBox(height: 10),
|
||||
getMedAidDetailsFields(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,645 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_dropdown_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_error_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_success_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_text_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_button.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/patients.dart';
|
||||
import 'package:supertokens_flutter/supertokens.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
|
||||
class EditPatient extends StatefulWidget {
|
||||
final Patient selectedPatient;
|
||||
final AppUser signedInUser;
|
||||
const EditPatient({
|
||||
super.key,
|
||||
required this.selectedPatient,
|
||||
required this.signedInUser,
|
||||
});
|
||||
|
||||
@override
|
||||
State<EditPatient> createState() => _EditPatientState();
|
||||
}
|
||||
|
||||
class _EditPatientState extends State<EditPatient> {
|
||||
var idController = TextEditingController();
|
||||
final fnameController = TextEditingController();
|
||||
final lnameController = TextEditingController();
|
||||
final cellController = TextEditingController();
|
||||
final emailController = TextEditingController();
|
||||
final medNoController = TextEditingController();
|
||||
final medNameController = TextEditingController();
|
||||
final medSchemeController = TextEditingController();
|
||||
final addressController = TextEditingController();
|
||||
final medAidController = TextEditingController();
|
||||
final medMainMemController = TextEditingController();
|
||||
final medAidCodeController = TextEditingController();
|
||||
final baseAPI = AppEnviroment.baseApiUrl;
|
||||
final docOfficeIdApiUrl = "${AppEnviroment.baseApiUrl}/users/profile/";
|
||||
final apiUrlEdit = "${AppEnviroment.baseApiUrl}/patients/update/";
|
||||
final apiUrlDelete = "${AppEnviroment.baseApiUrl}/patients/delete/";
|
||||
|
||||
late int futureDocOfficeId;
|
||||
late String userEmail;
|
||||
late bool medRequired;
|
||||
|
||||
late double width;
|
||||
late double height;
|
||||
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
|
||||
// Future getOfficeIdByUser(String endpoint) async {
|
||||
// final response = await http.get(Uri.parse(endpoint));
|
||||
// if (response.statusCode == 200) {
|
||||
// String body = response.body;
|
||||
// var decodedData = jsonDecode(body);
|
||||
// AppUser u = AppUser.fromJson(decodedData as Map<String, dynamic>);
|
||||
// setState(() {
|
||||
// //futureDocOfficeId = u.docOffice_id;
|
||||
// //print(futureDocOfficeId);
|
||||
// });
|
||||
// } else {
|
||||
// internetConnectionPopUp();
|
||||
// throw Exception('failed to load patients');
|
||||
// }
|
||||
// }
|
||||
|
||||
Future<void> updatePatientApiCall() async {
|
||||
//print("Here1");
|
||||
//userEmail = getLoginUserEmail() as String;
|
||||
//print(userEmail);
|
||||
//print("Here2");
|
||||
//await getOfficeIdByUser(docOfficeIdApiUrl + userEmail);
|
||||
//print(futureDocOfficeId.toString());
|
||||
//print("Here3");
|
||||
var response = await http.put(
|
||||
Uri.parse(apiUrlEdit),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
"id_no": idController.text,
|
||||
"first_name": fnameController.text,
|
||||
"last_name": lnameController.text,
|
||||
"email": emailController.text,
|
||||
"cell_no": cellController.text,
|
||||
"medical_aid": medAidController.text,
|
||||
"medical_aid_main_member": medMainMemController.text,
|
||||
"medical_aid_no": medNoController.text,
|
||||
"medical_aid_code": medAidCodeController.text,
|
||||
"medical_aid_name": medNameController.text,
|
||||
"medical_aid_scheme": medSchemeController.text,
|
||||
"address": addressController.text,
|
||||
"app_id": widget.selectedPatient.app_id,
|
||||
}),
|
||||
);
|
||||
// print("Here4");
|
||||
// print(response.statusCode);
|
||||
if (response.statusCode == 200) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pushNamed('/patient-profile',
|
||||
arguments: PatientViewArguments(
|
||||
widget.signedInUser, null, null, null, "personal"));
|
||||
//Navigator.of(context).pushNamed('/');
|
||||
String message =
|
||||
"${fnameController.text} ${lnameController.text}'s information has been updated successfully! Their medical records and details are now current.";
|
||||
successPopUp(message);
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deletePatientApiCall() async {
|
||||
//print("Here1");
|
||||
//userEmail = getLoginUserEmail() as String;
|
||||
//print(userEmail);
|
||||
//print("Here2");
|
||||
//await getOfficeIdByUser(docOfficeIdApiUrl + userEmail);
|
||||
//print("Office ID: ${futureDocOfficeId.toString()}");
|
||||
//print("OPatient ID No: ${idController.text}");
|
||||
//print("Here3");
|
||||
var response = await http.delete(
|
||||
Uri.parse(apiUrlDelete),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(
|
||||
<String, dynamic>{"app_id": widget.selectedPatient.app_id}),
|
||||
);
|
||||
//print("Here4");
|
||||
//print(response.statusCode);
|
||||
if (response.statusCode == 200) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).popAndPushNamed('/patient-profile',
|
||||
arguments: PatientViewArguments(
|
||||
widget.signedInUser, null, null, null, "personal"));
|
||||
String message =
|
||||
"${fnameController.text} ${lnameController.text}'s record has been deleted successfully. This means it will no longer be visible in patient manager and cannot be used for future appointments.";
|
||||
successPopUp(message);
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getLoginUserEmail() async {
|
||||
var uid = await SuperTokens.getUserId();
|
||||
var response = await http.get(Uri.parse("$baseAPI/user/$uid"));
|
||||
if (response.statusCode == 200) {
|
||||
var user = jsonDecode(response.body);
|
||||
userEmail = user["email"];
|
||||
}
|
||||
}
|
||||
|
||||
void messagePopUp(error) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(error),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void internetConnectionPopUp() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Internet Connection");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void deletePatientPopUp() {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => Dialog(
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
width: 700.0,
|
||||
height: (height / 3) * 2,
|
||||
decoration: BoxDecoration(
|
||||
color: MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
borderRadius: BorderRadius.circular(25.0),
|
||||
border: Border.all(
|
||||
color:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
width: 5.0),
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
//mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.warning_amber_rounded,
|
||||
size: 100,
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Text(
|
||||
"Are you sure you want to delete this?",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
fontSize: 25.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 25.0),
|
||||
child: Text(
|
||||
"This action is permanent! Deleting ${fnameController.text} ${lnameController.text} will remove him\\her from your account. You won't be able to recover it once it's gone.",
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
fontSize: 15.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 25.0),
|
||||
child: Text(
|
||||
"Here's what you'll be deleting:",
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
fontSize: 20.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 25.0),
|
||||
child: SizedBox(
|
||||
width: 450,
|
||||
child: Text(
|
||||
"1) Patient Profile Information.\n2) Patient Notes\n3) Patient Files.",
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
fontSize: 15.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
height: 50,
|
||||
child: MIHButton(
|
||||
onTap: deletePatientApiCall,
|
||||
buttonText: "Delete",
|
||||
buttonColor: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void successPopUp(String message) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MIHSuccessMessage(
|
||||
successType: "Success",
|
||||
successMessage: message,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
bool isFieldsFilled() {
|
||||
if (medRequired) {
|
||||
if (idController.text.isEmpty ||
|
||||
fnameController.text.isEmpty ||
|
||||
lnameController.text.isEmpty ||
|
||||
cellController.text.isEmpty ||
|
||||
emailController.text.isEmpty ||
|
||||
medNoController.text.isEmpty ||
|
||||
medNameController.text.isEmpty ||
|
||||
medSchemeController.text.isEmpty ||
|
||||
addressController.text.isEmpty ||
|
||||
medAidController.text.isEmpty ||
|
||||
medMainMemController.text.isEmpty ||
|
||||
medAidCodeController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (idController.text.isEmpty ||
|
||||
fnameController.text.isEmpty ||
|
||||
lnameController.text.isEmpty ||
|
||||
cellController.text.isEmpty ||
|
||||
emailController.text.isEmpty ||
|
||||
addressController.text.isEmpty ||
|
||||
medAidController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void isRequired() {
|
||||
//print("listerner triggered");
|
||||
if (medAidController.text == "Yes") {
|
||||
setState(() {
|
||||
medRequired = true;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
medRequired = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Widget displayForm() {
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
"Personal Details",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 25.0,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25.0),
|
||||
MIHTextField(
|
||||
controller: idController,
|
||||
hintText: "13 digit ID Number or Passport",
|
||||
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: "Last Name",
|
||||
editable: false,
|
||||
required: true,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: cellController,
|
||||
hintText: "Cell Number",
|
||||
editable: true,
|
||||
required: true,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: emailController,
|
||||
hintText: "Email",
|
||||
editable: false,
|
||||
required: true,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: addressController,
|
||||
hintText: "Address",
|
||||
editable: true,
|
||||
required: true,
|
||||
),
|
||||
const SizedBox(height: 15.0),
|
||||
Text(
|
||||
"Medical Aid Details",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 25.0,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHDropdownField(
|
||||
controller: medAidController,
|
||||
hintText: "Medical Aid",
|
||||
onSelect: (selected) {
|
||||
if (selected == "Yes") {
|
||||
setState(() {
|
||||
medRequired = true;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
medRequired = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
editable: true,
|
||||
required: true,
|
||||
dropdownOptions: const ["Yes", "No"],
|
||||
),
|
||||
Visibility(
|
||||
visible: medRequired,
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 10.0),
|
||||
MIHDropdownField(
|
||||
controller: medMainMemController,
|
||||
hintText: "Main Member.",
|
||||
editable: medRequired,
|
||||
required: medRequired,
|
||||
dropdownOptions: const ["Yes", "No"],
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: medNoController,
|
||||
hintText: "Medical Aid No.",
|
||||
editable: medRequired,
|
||||
required: medRequired,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: medAidCodeController,
|
||||
hintText: "Medical Aid Code",
|
||||
editable: medRequired,
|
||||
required: medRequired,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: medNameController,
|
||||
hintText: "Medical Aid Name",
|
||||
editable: medRequired,
|
||||
required: medRequired,
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MIHTextField(
|
||||
controller: medSchemeController,
|
||||
hintText: "Medical Aid Scheme",
|
||||
editable: medRequired,
|
||||
required: medRequired,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30.0),
|
||||
SizedBox(
|
||||
width: 500.0,
|
||||
height: 50.0,
|
||||
child: MIHButton(
|
||||
onTap: () {
|
||||
submitForm();
|
||||
},
|
||||
buttonText: "Update",
|
||||
buttonColor:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
textColor: MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void submitForm() {
|
||||
if (isFieldsFilled()) {
|
||||
if (!medRequired) {
|
||||
setState(() {
|
||||
medMainMemController.text = "";
|
||||
medNoController.text = "";
|
||||
medAidCodeController.text = "";
|
||||
medNameController.text = "";
|
||||
medSchemeController.text = "";
|
||||
});
|
||||
}
|
||||
updatePatientApiCall();
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Input Error");
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
idController.dispose();
|
||||
fnameController.dispose();
|
||||
lnameController.dispose();
|
||||
cellController.dispose();
|
||||
emailController.dispose();
|
||||
medNoController.dispose();
|
||||
medNameController.dispose();
|
||||
medSchemeController.dispose();
|
||||
addressController.dispose();
|
||||
medAidController.dispose();
|
||||
medMainMemController.dispose();
|
||||
medAidCodeController.dispose();
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
getLoginUserEmail();
|
||||
medAidController.addListener(isRequired);
|
||||
setState(() {
|
||||
idController.value = TextEditingValue(text: widget.selectedPatient.id_no);
|
||||
fnameController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.first_name);
|
||||
lnameController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.last_name);
|
||||
cellController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.cell_no);
|
||||
emailController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.email);
|
||||
medNameController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.medical_aid_name);
|
||||
medNoController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.medical_aid_no);
|
||||
medSchemeController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.medical_aid_scheme);
|
||||
addressController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.address);
|
||||
medAidController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.medical_aid);
|
||||
medMainMemController.value = TextEditingValue(
|
||||
text: widget.selectedPatient.medical_aid_main_member);
|
||||
medAidCodeController.value =
|
||||
TextEditingValue(text: widget.selectedPatient.medical_aid_code);
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
setState(() {
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
});
|
||||
|
||||
return Scaffold(
|
||||
// appBar: const MIHAppBar(
|
||||
// barTitle: "Edit Patient",
|
||||
// propicFile: null,
|
||||
// ),
|
||||
body: SafeArea(
|
||||
child: Stack(
|
||||
children: [
|
||||
KeyboardListener(
|
||||
focusNode: _focusNode,
|
||||
autofocus: true,
|
||||
onKeyEvent: (event) async {
|
||||
if (event is KeyDownEvent &&
|
||||
event.logicalKey == LogicalKeyboardKey.enter) {
|
||||
submitForm();
|
||||
}
|
||||
},
|
||||
child: displayForm(),
|
||||
),
|
||||
Positioned(
|
||||
top: 10,
|
||||
left: 5,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 10,
|
||||
right: 5,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
color:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
//alignment: Alignment.topRight,
|
||||
onPressed: () {
|
||||
deletePatientPopUp();
|
||||
},
|
||||
))
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,679 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/mih_packages/patient_profile/builder/buildFilesList.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_file_input.dart';
|
||||
import 'package:patient_manager/mih_components/med_cert_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_error_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_success_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_button.dart';
|
||||
import 'package:patient_manager/mih_packages/patient_profile/prescipInput.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/business.dart';
|
||||
import 'package:patient_manager/objects/businessUser.dart';
|
||||
import 'package:patient_manager/objects/files.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
import 'package:http/http.dart' as http2;
|
||||
import 'package:supertokens_flutter/supertokens.dart';
|
||||
|
||||
import '../../objects/patients.dart';
|
||||
|
||||
class PatientFiles extends StatefulWidget {
|
||||
final int patientIndex;
|
||||
final Patient selectedPatient;
|
||||
final AppUser signedInUser;
|
||||
final Business? business;
|
||||
final BusinessUser? businessUser;
|
||||
final String type;
|
||||
|
||||
const PatientFiles({
|
||||
super.key,
|
||||
required this.patientIndex,
|
||||
required this.selectedPatient,
|
||||
required this.signedInUser,
|
||||
required this.business,
|
||||
required this.businessUser,
|
||||
required this.type,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PatientFiles> createState() => _PatientFilesState();
|
||||
}
|
||||
|
||||
class _PatientFilesState extends State<PatientFiles> {
|
||||
String endpointFiles = "${AppEnviroment.baseApiUrl}/files/patients/";
|
||||
String endpointUser = "${AppEnviroment.baseApiUrl}/users/profile/";
|
||||
String endpointGenFiles =
|
||||
"${AppEnviroment.baseApiUrl}/files/generate/med-cert/";
|
||||
String endpointFileUpload = "${AppEnviroment.baseApiUrl}/files/upload/file/";
|
||||
String endpointInsertFiles = "${AppEnviroment.baseApiUrl}/files/insert/";
|
||||
|
||||
final startDateController = TextEditingController();
|
||||
final endDateTextController = TextEditingController();
|
||||
final retDateTextController = TextEditingController();
|
||||
final selectedFileController = TextEditingController();
|
||||
final medicineController = TextEditingController();
|
||||
final quantityController = TextEditingController();
|
||||
final dosageController = TextEditingController();
|
||||
final timesDailyController = TextEditingController();
|
||||
final noDaysController = TextEditingController();
|
||||
final noRepeatsController = TextEditingController();
|
||||
final outputController = TextEditingController();
|
||||
|
||||
late Future<List<PFile>> futueFiles;
|
||||
late String userEmail = "";
|
||||
late PlatformFile selected;
|
||||
final baseAPI = AppEnviroment.baseApiUrl;
|
||||
|
||||
Future<void> generateMedCert() async {
|
||||
//start loading circle
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
|
||||
var response1 = await http.post(
|
||||
Uri.parse("${AppEnviroment.baseApiUrl}/minio/generate/med-cert/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
"app_id": widget.selectedPatient.app_id,
|
||||
"fullName":
|
||||
"${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}",
|
||||
"id_no": widget.selectedPatient.id_no,
|
||||
"docfname":
|
||||
"DR. ${widget.signedInUser.fname} ${widget.signedInUser.lname}",
|
||||
"startDate": startDateController.text,
|
||||
"busName": widget.business!.Name,
|
||||
"busAddr": "*TO BE ADDED IN THE FUTURE*",
|
||||
"busNo": widget.business!.contact_no,
|
||||
"busEmail": widget.business!.bus_email,
|
||||
"endDate": endDateTextController.text,
|
||||
"returnDate": retDateTextController.text,
|
||||
"logo_path": widget.business!.logo_path,
|
||||
"sig_path": widget.businessUser!.sig_path,
|
||||
}),
|
||||
);
|
||||
//print(response1.statusCode);
|
||||
DateTime now = new DateTime.now();
|
||||
DateTime date = new DateTime(now.year, now.month, now.day);
|
||||
String fileName =
|
||||
"Med-Cert-${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}-${date.toString().substring(0, 10)}.pdf";
|
||||
if (response1.statusCode == 200) {
|
||||
var response2 = await http.post(
|
||||
Uri.parse("${AppEnviroment.baseApiUrl}/files/insert/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
"file_path":
|
||||
"${widget.selectedPatient.app_id}/patient_files/$fileName",
|
||||
"file_name": fileName,
|
||||
"app_id": widget.selectedPatient.app_id
|
||||
}),
|
||||
);
|
||||
//print(response2.statusCode);
|
||||
if (response2.statusCode == 201) {
|
||||
setState(() {
|
||||
startDateController.clear();
|
||||
endDateTextController.clear();
|
||||
retDateTextController.clear();
|
||||
futueFiles = fetchFiles();
|
||||
});
|
||||
// end loading circle
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
String message =
|
||||
"The medical certificate $fileName has been successfully generated and added to ${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}'s record. You can now access and download it for their use.";
|
||||
successPopUp(message);
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> uploadSelectedFile(PlatformFile file) async {
|
||||
//var strem = new http.ByteStream.fromBytes(file.bytes.)
|
||||
//start loading circle
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
|
||||
var token = await SuperTokens.getAccessToken();
|
||||
//print(t);
|
||||
//print("here1");
|
||||
var request = http2.MultipartRequest(
|
||||
'POST', Uri.parse("${AppEnviroment.baseApiUrl}/minio/upload/file/"));
|
||||
request.headers['accept'] = 'application/json';
|
||||
request.headers['Authorization'] = 'Bearer $token';
|
||||
request.headers['Content-Type'] = 'multipart/form-data';
|
||||
request.fields['app_id'] = widget.selectedPatient.app_id;
|
||||
request.fields['folder'] = "patient_files";
|
||||
request.files.add(await http2.MultipartFile.fromBytes('file', file.bytes!,
|
||||
filename: file.name.replaceAll(RegExp(r' '), '-')));
|
||||
//print("here2");
|
||||
var response1 = await request.send();
|
||||
//print("here3");
|
||||
//print(response1.statusCode);
|
||||
//print(response1.toString());
|
||||
if (response1.statusCode == 200) {
|
||||
//print("here3");
|
||||
var fname = file.name.replaceAll(RegExp(r' '), '-');
|
||||
var filePath = "${widget.selectedPatient.app_id}/patient_files/$fname";
|
||||
var response2 = await http.post(
|
||||
Uri.parse("${AppEnviroment.baseApiUrl}/files/insert/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
"file_path": filePath,
|
||||
"file_name": fname,
|
||||
"app_id": widget.selectedPatient.app_id
|
||||
}),
|
||||
);
|
||||
//print("here5");
|
||||
//print(response2.statusCode);
|
||||
if (response2.statusCode == 201) {
|
||||
setState(() {
|
||||
selectedFileController.clear();
|
||||
futueFiles = fetchFiles();
|
||||
});
|
||||
// end loading circle
|
||||
Navigator.of(context).pop();
|
||||
String message =
|
||||
"The file ${file.name.replaceAll(RegExp(r' '), '-')} has been successfully generated and added to ${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}'s record. You can now access and download it for their use.";
|
||||
successPopUp(message);
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<PFile>> fetchFiles() async {
|
||||
final response = await http.get(Uri.parse(
|
||||
"${AppEnviroment.baseApiUrl}/files/patients/${widget.selectedPatient.app_id}"));
|
||||
|
||||
//print(response.statusCode);
|
||||
//print(response.body);
|
||||
if (response.statusCode == 200) {
|
||||
Iterable l = jsonDecode(response.body);
|
||||
List<PFile> files =
|
||||
List<PFile>.from(l.map((model) => PFile.fromJson(model)));
|
||||
return files;
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
throw Exception('failed to load patients');
|
||||
}
|
||||
}
|
||||
|
||||
void successPopUp(String message) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MIHSuccessMessage(
|
||||
successType: "Success",
|
||||
successMessage: message,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void messagePopUp(error) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(error),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void medCertPopUp() {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => Dialog(
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
width: 700.0,
|
||||
//height: 475.0,
|
||||
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: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"Create Medical Certificate",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
fontSize: 35.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25.0),
|
||||
Medcertinput(
|
||||
startDateController: startDateController,
|
||||
endDateTextController: endDateTextController,
|
||||
retDateTextController: retDateTextController,
|
||||
),
|
||||
const SizedBox(height: 30.0),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
height: 50,
|
||||
child: MIHButton(
|
||||
buttonText: "Generate",
|
||||
buttonColor: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
textColor:
|
||||
MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
onTap: () async {
|
||||
if (isMedCertFieldsFilled()) {
|
||||
await generateMedCert();
|
||||
//Navigator.pop(context);
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(
|
||||
errorType: "Input Error");
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void prescritionPopUp() {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => Dialog(
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
width: 900.0,
|
||||
//height: 475.0,
|
||||
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: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"Create Perscription",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
fontSize: 35.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25.0),
|
||||
PrescripInput(
|
||||
medicineController: medicineController,
|
||||
quantityController: quantityController,
|
||||
dosageController: dosageController,
|
||||
timesDailyController: timesDailyController,
|
||||
noDaysController: noDaysController,
|
||||
noRepeatsController: noRepeatsController,
|
||||
outputController: outputController,
|
||||
selectedPatient: widget.selectedPatient,
|
||||
signedInUser: widget.signedInUser,
|
||||
business: widget.business,
|
||||
businessUser: widget.businessUser,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
right: 5,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
medicineController.clear();
|
||||
quantityController.clear();
|
||||
dosageController.clear();
|
||||
timesDailyController.clear();
|
||||
noDaysController.clear();
|
||||
noRepeatsController.clear();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.close,
|
||||
color: MzanziInnovationHub.of(context)!.theme.errorColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void uploudFilePopUp() {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => Dialog(
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
width: 700.0,
|
||||
//height: 475.0,
|
||||
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: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"Upload File",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
fontSize: 35.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25.0),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: MIHFileField(
|
||||
controller: selectedFileController,
|
||||
hintText: "Select File",
|
||||
editable: false,
|
||||
required: true,
|
||||
onPressed: () async {
|
||||
FilePickerResult? result =
|
||||
await FilePicker.platform.pickFiles(
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ['jpg', 'png', 'pdf'],
|
||||
);
|
||||
if (result == null) return;
|
||||
final selectedFile = result.files.first;
|
||||
setState(() {
|
||||
selected = selectedFile;
|
||||
});
|
||||
|
||||
setState(() {
|
||||
selectedFileController.text = selectedFile.name;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
height: 50,
|
||||
child: MIHButton(
|
||||
buttonText: "Add File",
|
||||
buttonColor: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
textColor:
|
||||
MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
onTap: () {
|
||||
if (isFileFieldsFilled()) {
|
||||
uploadSelectedFile(selected);
|
||||
Navigator.pop(context);
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(
|
||||
errorType: "Input Error");
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void internetConnectionPopUp() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Internet Connection");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
bool isMedCertFieldsFilled() {
|
||||
if (startDateController.text.isEmpty ||
|
||||
endDateTextController.text.isEmpty ||
|
||||
retDateTextController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool isFileFieldsFilled() {
|
||||
if (selectedFileController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
List<Widget> setIcons() {
|
||||
if (widget.type == "personal") {
|
||||
return [
|
||||
Text(
|
||||
"Documents",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
uploudFilePopUp();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.add,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
)
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
Text(
|
||||
"Documents",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
medCertPopUp();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.sick_outlined,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
prescritionPopUp();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.medication_outlined,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
uploudFilePopUp();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.add,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
startDateController.dispose();
|
||||
endDateTextController.dispose();
|
||||
retDateTextController.dispose();
|
||||
selectedFileController.dispose();
|
||||
medicineController.dispose();
|
||||
quantityController.dispose();
|
||||
dosageController.dispose();
|
||||
timesDailyController.dispose();
|
||||
noDaysController.dispose();
|
||||
noRepeatsController.dispose();
|
||||
outputController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
futueFiles = fetchFiles();
|
||||
//patientDetails = getPatientDetails() as Patient;
|
||||
//getUserDetails();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder(
|
||||
future: futueFiles,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Center(
|
||||
child: Mihloadingcircle(),
|
||||
);
|
||||
} else if (snapshot.hasData) {
|
||||
final filesList = snapshot.data!;
|
||||
return Column(children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: setIcons(),
|
||||
),
|
||||
Divider(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
|
||||
const SizedBox(height: 10),
|
||||
BuildFilesList(
|
||||
files: filesList,
|
||||
signedInUser: widget.signedInUser,
|
||||
selectedPatient: widget.selectedPatient,
|
||||
business: widget.business,
|
||||
businessUser: widget.businessUser,
|
||||
),
|
||||
]);
|
||||
} else {
|
||||
return const Center(
|
||||
child: Text("Error Loading Notes"),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,536 @@
|
||||
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/mih_packages/patient_profile/builder/buildPatientList.dart';
|
||||
import 'package:patient_manager/mih_packages/patient_profile/builder/buildPatientQueueList.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_date_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_error_message.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/mih_components/mih_inputs_and_buttons/mih_search_input.dart';
|
||||
import 'package:patient_manager/env/env.dart';
|
||||
import 'package:patient_manager/main.dart';
|
||||
import 'package:patient_manager/objects/patients.dart';
|
||||
|
||||
class PatientManager extends StatefulWidget {
|
||||
//final AppUser signedInUser;
|
||||
final BusinessArguments arguments;
|
||||
const PatientManager({
|
||||
super.key,
|
||||
required this.arguments,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PatientManager> createState() => _PatientManagerState();
|
||||
}
|
||||
|
||||
//
|
||||
class _PatientManagerState extends State<PatientManager> {
|
||||
TextEditingController searchController = TextEditingController();
|
||||
TextEditingController queueDateController = TextEditingController();
|
||||
|
||||
String baseUrl = AppEnviroment.baseApiUrl;
|
||||
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
String errorCode = "";
|
||||
String errorBody = "";
|
||||
|
||||
String searchString = "";
|
||||
var now = DateTime.now();
|
||||
var formatter = DateFormat('yyyy-MM-dd');
|
||||
late String formattedDate;
|
||||
bool start = true;
|
||||
int _selectedIndex = 0;
|
||||
|
||||
late Future<List<Patient>> patientSearchResults;
|
||||
late Future<List<PatientQueue>> patientQueueResults;
|
||||
|
||||
Future<List<PatientQueue>> fetchPatientQueue(String date) async {
|
||||
//print("Patien manager page: $endpoint");
|
||||
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}");
|
||||
errorCode = response.statusCode.toString();
|
||||
errorBody = response.body;
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
//print("Here1");
|
||||
Iterable l = jsonDecode(response.body);
|
||||
//print("Here2");
|
||||
List<PatientQueue> patientQueue = List<PatientQueue>.from(
|
||||
l.map((model) => PatientQueue.fromJson(model)));
|
||||
//print("Here3");
|
||||
//print(patientQueue);
|
||||
return patientQueue;
|
||||
} else {
|
||||
throw Exception('failed to load patients');
|
||||
}
|
||||
}
|
||||
|
||||
List<PatientQueue> filterQueueResults(
|
||||
List<PatientQueue> queueList, String query) {
|
||||
List<PatientQueue> templist = [];
|
||||
//print(query);
|
||||
for (var item in queueList) {
|
||||
if (item.date_time.contains(query)) {
|
||||
//print(item.medical_aid_no);
|
||||
templist.add(item);
|
||||
}
|
||||
}
|
||||
//print(templist);
|
||||
return templist;
|
||||
}
|
||||
|
||||
Future<List<Patient>> 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<Patient> patients =
|
||||
List<Patient>.from(l.map((model) => Patient.fromJson(model)));
|
||||
return patients;
|
||||
} else {
|
||||
throw Exception('failed to load patients');
|
||||
}
|
||||
}
|
||||
|
||||
List<Patient> filterSearchResults(List<Patient> patList, String query) {
|
||||
List<Patient> templist = [];
|
||||
//print(query);
|
||||
for (var item in patList) {
|
||||
if (item.id_no.contains(searchString) ||
|
||||
item.medical_aid_no.contains(searchString)) {
|
||||
//print(item.medical_aid_no);
|
||||
templist.add(item);
|
||||
}
|
||||
}
|
||||
return templist;
|
||||
}
|
||||
|
||||
Widget displayPatientList(List<Patient> patientsList, String searchString) {
|
||||
if (searchString.isNotEmpty && searchString != "") {
|
||||
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: BuildPatientsList(
|
||||
patients: patientsList,
|
||||
signedInUser: widget.arguments.signedInUser,
|
||||
business: widget.arguments.business,
|
||||
arguments: widget.arguments,
|
||||
),
|
||||
);
|
||||
}
|
||||
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 patientSearch(double w, double h) {
|
||||
return KeyboardListener(
|
||||
focusNode: _focusNode,
|
||||
autofocus: true,
|
||||
onKeyEvent: (event) async {
|
||||
if (event is KeyDownEvent &&
|
||||
event.logicalKey == LogicalKeyboardKey.enter) {
|
||||
submitPatientForm();
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
width: w,
|
||||
height: h - 157,
|
||||
child: Column(mainAxisSize: MainAxisSize.max, children: [
|
||||
const SizedBox(height: 5),
|
||||
const Text(
|
||||
"Patient Search",
|
||||
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
MIHSearchField(
|
||||
controller: searchController,
|
||||
hintText: "ID or Medical Aid No. Search",
|
||||
required: true,
|
||||
editable: true,
|
||||
onTap: () {
|
||||
submitPatientForm();
|
||||
},
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
FutureBuilder(
|
||||
future: patientSearchResults,
|
||||
builder: (context, snapshot) {
|
||||
//print("patient Liust ${snapshot.data}");
|
||||
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 &&
|
||||
snapshot.hasData) {
|
||||
List<Patient> patientsList;
|
||||
if (searchString == "") {
|
||||
patientsList = [];
|
||||
} else {
|
||||
patientsList =
|
||||
filterSearchResults(snapshot.data!, searchString);
|
||||
//print(patientsList);
|
||||
}
|
||||
|
||||
return Expanded(
|
||||
child: displayPatientList(patientsList, searchString),
|
||||
);
|
||||
} else {
|
||||
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: 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,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget displayQueueList(List<PatientQueue> 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,
|
||||
business: widget.arguments.business,
|
||||
businessUser: widget.arguments.businessUser,
|
||||
),
|
||||
);
|
||||
}
|
||||
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(
|
||||
"No Appointments for $formattedDate",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
color: MzanziInnovationHub.of(context)!.theme.messageTextColor()),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget patientQueue(double w, double h) {
|
||||
return SizedBox(
|
||||
width: w,
|
||||
height: h - 157,
|
||||
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),
|
||||
MIHDateField(
|
||||
controller: queueDateController,
|
||||
lableText: "Date",
|
||||
required: true,
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
FutureBuilder(
|
||||
future: patientQueueResults,
|
||||
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<PatientQueue> patientQueueList;
|
||||
// if (searchString == "") {
|
||||
// patientQueueList = [];
|
||||
// } else {
|
||||
patientQueueList = filterQueueResults(
|
||||
snapshot.requireData, queueDateController.text);
|
||||
// print(patientQueueList);
|
||||
// }
|
||||
|
||||
return Expanded(
|
||||
child: displayQueueList(patientQueueList),
|
||||
);
|
||||
} else {
|
||||
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: 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 refreshQueue() {
|
||||
setState(() {
|
||||
start = true;
|
||||
});
|
||||
checkforchange();
|
||||
}
|
||||
|
||||
void submitPatientForm() {
|
||||
if (searchController.text != "") {
|
||||
setState(() {
|
||||
searchString = searchController.text;
|
||||
patientSearchResults = fetchPatients(searchString);
|
||||
});
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Input Error");
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void checkforchange() {
|
||||
if (start == true) {
|
||||
setState(() {
|
||||
patientQueueResults = fetchPatientQueue(queueDateController.text);
|
||||
start = false;
|
||||
});
|
||||
}
|
||||
if (formattedDate != queueDateController.text) {
|
||||
setState(() {
|
||||
patientQueueResults = fetchPatientQueue(queueDateController.text);
|
||||
formattedDate = queueDateController.text;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Widget showSelection(int index, double screenWidth, double screenHeight) {
|
||||
if (index == 0) {
|
||||
return SizedBox(
|
||||
//width: 660,
|
||||
child: patientQueue(screenWidth, screenHeight),
|
||||
);
|
||||
} else {
|
||||
return SizedBox(
|
||||
//width: 660,
|
||||
child: patientSearch(screenWidth, screenHeight),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
searchController.dispose();
|
||||
queueDateController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
patientSearchResults = fetchPatients("abc");
|
||||
queueDateController.addListener(checkforchange);
|
||||
setState(() {
|
||||
formattedDate = formatter.format(now);
|
||||
queueDateController.text = formattedDate;
|
||||
});
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
final screenHeight = MediaQuery.of(context).size.height;
|
||||
return Scaffold(
|
||||
// appBar: const MIHAppBar(
|
||||
// barTitle: "Patient Manager",
|
||||
// propicFile: null,
|
||||
// ),
|
||||
body: Stack(
|
||||
children: [
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 5),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_selectedIndex = 0;
|
||||
});
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.people,
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_selectedIndex = 1;
|
||||
});
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.search,
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
refreshQueue();
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.refresh,
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 15),
|
||||
child: showSelection(_selectedIndex, screenWidth, screenHeight),
|
||||
),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
left: 5,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/mih_packages/patient_profile/builder/buildNotesList.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_error_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_multiline_text_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_success_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_text_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_button.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/business.dart';
|
||||
import 'package:patient_manager/objects/businessUser.dart';
|
||||
import 'package:patient_manager/objects/notes.dart';
|
||||
import 'package:patient_manager/objects/patients.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
|
||||
class PatientNotes extends StatefulWidget {
|
||||
final String patientAppId;
|
||||
final Patient selectedPatient;
|
||||
final AppUser signedInUser;
|
||||
final Business? business;
|
||||
final BusinessUser? businessUser;
|
||||
final String type;
|
||||
const PatientNotes({
|
||||
super.key,
|
||||
required this.patientAppId,
|
||||
required this.selectedPatient,
|
||||
required this.signedInUser,
|
||||
required this.business,
|
||||
required this.businessUser,
|
||||
required this.type,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PatientNotes> createState() => _PatientNotesState();
|
||||
}
|
||||
|
||||
class _PatientNotesState extends State<PatientNotes> {
|
||||
String endpoint = "${AppEnviroment.baseApiUrl}/notes/patients/";
|
||||
String apiUrlAddNote = "${AppEnviroment.baseApiUrl}/notes/insert/";
|
||||
final titleController = TextEditingController();
|
||||
final noteTextController = TextEditingController();
|
||||
final officeController = TextEditingController();
|
||||
final dateController = TextEditingController();
|
||||
final doctorController = TextEditingController();
|
||||
late Future<List<Note>> futueNotes;
|
||||
|
||||
Future<List<Note>> fetchNotes(String endpoint) async {
|
||||
final response = await http.get(Uri.parse(
|
||||
"${AppEnviroment.baseApiUrl}/notes/patients/${widget.selectedPatient.app_id}"));
|
||||
if (response.statusCode == 200) {
|
||||
Iterable l = jsonDecode(response.body);
|
||||
List<Note> notes =
|
||||
List<Note>.from(l.map((model) => Note.fromJson(model)));
|
||||
//print("Here notes");
|
||||
return notes;
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
throw Exception('failed to load patients');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> addPatientNoteAPICall() async {
|
||||
// String title = "";
|
||||
// if (widget.businessUser!.title == "Doctor") {
|
||||
// title = "Dr.";
|
||||
// }
|
||||
var response = await http.post(
|
||||
Uri.parse("${AppEnviroment.baseApiUrl}/notes/insert/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
"note_name": titleController.text,
|
||||
"note_text": noteTextController.text,
|
||||
"doc_office": officeController.text,
|
||||
"doctor": doctorController.text,
|
||||
"app_id": widget.selectedPatient.app_id,
|
||||
}),
|
||||
);
|
||||
if (response.statusCode == 201) {
|
||||
setState(() {
|
||||
futueNotes = fetchNotes(endpoint + widget.patientAppId.toString());
|
||||
});
|
||||
// Navigator.of(context)
|
||||
// .pushNamed('/patient-manager', arguments: widget.userEmail);
|
||||
String message =
|
||||
"Your note has been successfully added to the patients medical record. You can now view it alongside their other important information.";
|
||||
successPopUp(message);
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
}
|
||||
|
||||
void successPopUp(String message) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MIHSuccessMessage(
|
||||
successType: "Success",
|
||||
successMessage: message,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void internetConnectionPopUp() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Internet Connection");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void messagePopUp(error) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(error),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void addNotePopUp() {
|
||||
DateTime now = new DateTime.now();
|
||||
DateTime date = new DateTime(now.year, now.month, now.day);
|
||||
var title = "";
|
||||
if (widget.businessUser!.title == "Doctor") {
|
||||
title = "Dr.";
|
||||
}
|
||||
setState(() {
|
||||
officeController.text = widget.business!.Name;
|
||||
doctorController.text =
|
||||
"$title ${widget.signedInUser.fname} ${widget.signedInUser.lname}";
|
||||
dateController.text = date.toString().substring(0, 10);
|
||||
});
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => Dialog(
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
width: 700.0,
|
||||
//height: 500.0,
|
||||
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: Column(
|
||||
//mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text(
|
||||
"Add Note",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
fontSize: 35.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25.0),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: MIHTextField(
|
||||
controller: officeController,
|
||||
hintText: "Office",
|
||||
editable: false,
|
||||
required: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: MIHTextField(
|
||||
controller: doctorController,
|
||||
hintText: "Created By",
|
||||
editable: false,
|
||||
required: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: MIHTextField(
|
||||
controller: dateController,
|
||||
hintText: "Created Date",
|
||||
editable: false,
|
||||
required: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: MIHTextField(
|
||||
controller: titleController,
|
||||
hintText: "Note Title",
|
||||
editable: true,
|
||||
required: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
Expanded(
|
||||
child: MIHMLTextField(
|
||||
controller: noteTextController,
|
||||
hintText: "Note Details",
|
||||
editable: true,
|
||||
required: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30.0),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
height: 50,
|
||||
child: MIHButton(
|
||||
onTap: () {
|
||||
if (isFieldsFilled()) {
|
||||
addPatientNoteAPICall();
|
||||
Navigator.pop(context);
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(
|
||||
errorType: "Input Error");
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
buttonText: "Add Note",
|
||||
buttonColor: MzanziInnovationHub.of(context)!
|
||||
.theme
|
||||
.secondaryColor(),
|
||||
textColor:
|
||||
MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
right: 5,
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
titleController.clear();
|
||||
noteTextController.clear();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.close,
|
||||
color: MzanziInnovationHub.of(context)!.theme.errorColor(),
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool isFieldsFilled() {
|
||||
if (titleController.text.isEmpty || noteTextController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
List<Widget> setIcons() {
|
||||
if (widget.type == "personal") {
|
||||
return [
|
||||
Text(
|
||||
"Notes",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
|
||||
),
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
Text(
|
||||
"Notes",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
addNotePopUp();
|
||||
},
|
||||
icon: Icon(Icons.add,
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
titleController.dispose();
|
||||
noteTextController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
futueNotes = fetchNotes(endpoint + widget.patientAppId);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder(
|
||||
future: futueNotes,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Center(
|
||||
child: Mihloadingcircle(),
|
||||
);
|
||||
} else if (snapshot.hasData) {
|
||||
final notesList = snapshot.data!;
|
||||
return Column(children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: setIcons(),
|
||||
),
|
||||
Divider(
|
||||
color: MzanziInnovationHub.of(context)!.theme.secondaryColor()),
|
||||
const SizedBox(height: 10),
|
||||
BuildNotesList(
|
||||
notes: notesList,
|
||||
signedInUser: widget.signedInUser,
|
||||
selectedPatient: widget.selectedPatient,
|
||||
business: widget.business,
|
||||
businessUser: widget.businessUser,
|
||||
),
|
||||
]);
|
||||
} else {
|
||||
return const Center(
|
||||
child: Text("Error Loading Notes"),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:patient_manager/mih_packages/patient_profile/patientDetails.dart';
|
||||
import 'package:patient_manager/mih_packages/patient_profile/patientFiles.dart';
|
||||
import 'package:patient_manager/mih_packages/patient_profile/patientNotes.dart';
|
||||
import 'package:patient_manager/mih_components/mih_layout/mih_action.dart';
|
||||
import 'package:patient_manager/mih_components/mih_layout/mih_body.dart';
|
||||
import 'package:patient_manager/mih_components/mih_layout/mih_header.dart';
|
||||
import 'package:patient_manager/mih_components/mih_layout/mih_layout_builder.dart';
|
||||
import 'package:patient_manager/env/env.dart';
|
||||
import 'package:patient_manager/main.dart';
|
||||
import 'package:patient_manager/objects/arguments.dart';
|
||||
import 'package:patient_manager/objects/patients.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
|
||||
class PatientView extends StatefulWidget {
|
||||
//final AppUser signedInUser;
|
||||
final PatientViewArguments arguments;
|
||||
const PatientView({
|
||||
super.key,
|
||||
required this.arguments,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PatientView> createState() => _PatientViewState();
|
||||
}
|
||||
|
||||
class _PatientViewState extends State<PatientView> {
|
||||
int _selectedIndex = 0;
|
||||
late double popUpWidth;
|
||||
late double? popUpheight;
|
||||
late double popUpTitleSize;
|
||||
late double popUpSubtitleSize;
|
||||
late double popUpBodySize;
|
||||
late double popUpIconSize;
|
||||
late double popUpPaddingSize;
|
||||
late double width;
|
||||
late double height;
|
||||
|
||||
Future<Patient?> fetchPatient() async {
|
||||
//print("Patien manager page: $endpoint");
|
||||
var patientAppId = widget.arguments.selectedPatient!.app_id;
|
||||
|
||||
final response = await http
|
||||
.get(Uri.parse("${AppEnviroment.baseApiUrl}/patients/$patientAppId"));
|
||||
// print("Here");
|
||||
// print("Body: ${response.body}");
|
||||
// print("Code: ${response.statusCode}");
|
||||
// var errorCode = response.statusCode.toString();
|
||||
// var errorBody = response.body;
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
//print("Here1");
|
||||
var decodedData = jsonDecode(response.body);
|
||||
// print("Here2");
|
||||
Patient patients = Patient.fromJson(decodedData as Map<String, dynamic>);
|
||||
// print("Here3");
|
||||
// print(patients);
|
||||
return patients;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void checkScreenSize() {
|
||||
if (MzanziInnovationHub.of(context)!.theme.screenType == "desktop") {
|
||||
setState(() {
|
||||
popUpWidth = (width / 4) * 2;
|
||||
popUpheight = null;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
popUpWidth = width - (width * 0.1);
|
||||
popUpheight = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Widget showSelection(int index) {
|
||||
if (index == 0) {
|
||||
return PatientDetails(
|
||||
signedInUser: widget.arguments.signedInUser,
|
||||
selectedPatient: widget.arguments.selectedPatient!,
|
||||
type: widget.arguments.type,
|
||||
);
|
||||
} else if (index == 1) {
|
||||
return PatientNotes(
|
||||
patientAppId: widget.arguments.selectedPatient!.app_id,
|
||||
selectedPatient: widget.arguments.selectedPatient!,
|
||||
signedInUser: widget.arguments.signedInUser,
|
||||
business: widget.arguments.business,
|
||||
businessUser: widget.arguments.businessUser,
|
||||
type: widget.arguments.type,
|
||||
);
|
||||
} else {
|
||||
return PatientFiles(
|
||||
patientIndex: widget.arguments.selectedPatient!.idpatients,
|
||||
selectedPatient: widget.arguments.selectedPatient!,
|
||||
signedInUser: widget.arguments.signedInUser,
|
||||
business: widget.arguments.business,
|
||||
businessUser: widget.arguments.businessUser,
|
||||
type: widget.arguments.type,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MIHAction getActionButton() {
|
||||
return MIHAction(
|
||||
icon: Icons.arrow_back,
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MIHHeader getHeader() {
|
||||
return MIHHeader(
|
||||
headerAlignment: MainAxisAlignment.end,
|
||||
headerItems: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_selectedIndex = 0;
|
||||
});
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.perm_identity,
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_selectedIndex = 1;
|
||||
});
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.article_outlined,
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_selectedIndex = 2;
|
||||
});
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.file_present,
|
||||
size: 35,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
MIHBody getBody() {
|
||||
return MIHBody(
|
||||
borderOn: true,
|
||||
bodyItems: [showSelection(_selectedIndex)],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
setState(() {
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
});
|
||||
checkScreenSize();
|
||||
return MIHLayoutBuilder(
|
||||
actionButton: getActionButton(),
|
||||
header: getHeader(),
|
||||
body: getBody(),
|
||||
);
|
||||
// return Scaffold(
|
||||
// body: SafeArea(
|
||||
// child: SingleChildScrollView(
|
||||
// child: Stack(
|
||||
// children: [
|
||||
// Container(
|
||||
// width: width,
|
||||
// height: height,
|
||||
// padding: const EdgeInsets.symmetric(
|
||||
// vertical: 10.0, horizontal: 15.0),
|
||||
// child: Column(
|
||||
// mainAxisSize: MainAxisSize.max,
|
||||
// children: [
|
||||
// Row(
|
||||
// crossAxisAlignment: CrossAxisAlignment.end,
|
||||
// mainAxisAlignment: MainAxisAlignment.end,
|
||||
// children: [
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// _selectedIndex = 0;
|
||||
// });
|
||||
// },
|
||||
// icon: const Icon(
|
||||
// Icons.perm_identity,
|
||||
// size: 35,
|
||||
// ),
|
||||
// ),
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// _selectedIndex = 1;
|
||||
// });
|
||||
// },
|
||||
// icon: const Icon(
|
||||
// Icons.article_outlined,
|
||||
// size: 35,
|
||||
// ),
|
||||
// ),
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// _selectedIndex = 2;
|
||||
// });
|
||||
// },
|
||||
// icon: const Icon(
|
||||
// Icons.file_present,
|
||||
// size: 35,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// const SizedBox(
|
||||
// height: 10.0,
|
||||
// ),
|
||||
// showSelection(_selectedIndex),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// Positioned(
|
||||
// top: 10,
|
||||
// left: 5,
|
||||
// width: 50,
|
||||
// height: 50,
|
||||
// child: IconButton(
|
||||
// onPressed: () {
|
||||
// Navigator.of(context).pop();
|
||||
// },
|
||||
// icon: const Icon(Icons.arrow_back),
|
||||
// ),
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,588 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:patient_manager/mih_components/medicine_search.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_dropdown_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_error_message.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_search_input.dart';
|
||||
import 'package:patient_manager/mih_components/mih_inputs_and_buttons/mih_button.dart';
|
||||
import 'package:patient_manager/mih_components/mih_pop_up_messages/mih_success_message.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/business.dart';
|
||||
import 'package:patient_manager/objects/businessUser.dart';
|
||||
import 'package:patient_manager/objects/patients.dart';
|
||||
import 'package:patient_manager/objects/perscription.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
|
||||
class PrescripInput extends StatefulWidget {
|
||||
final TextEditingController medicineController;
|
||||
final TextEditingController quantityController;
|
||||
final TextEditingController dosageController;
|
||||
final TextEditingController timesDailyController;
|
||||
final TextEditingController noDaysController;
|
||||
final TextEditingController noRepeatsController;
|
||||
final TextEditingController outputController;
|
||||
final Patient selectedPatient;
|
||||
final AppUser signedInUser;
|
||||
final Business? business;
|
||||
final BusinessUser? businessUser;
|
||||
const PrescripInput({
|
||||
super.key,
|
||||
required this.medicineController,
|
||||
required this.quantityController,
|
||||
required this.dosageController,
|
||||
required this.timesDailyController,
|
||||
required this.noDaysController,
|
||||
required this.noRepeatsController,
|
||||
required this.outputController,
|
||||
required this.selectedPatient,
|
||||
required this.signedInUser,
|
||||
required this.business,
|
||||
required this.businessUser,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PrescripInput> createState() => _PrescripInputState();
|
||||
}
|
||||
|
||||
class _PrescripInputState extends State<PrescripInput> {
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
List<Perscription> perscriptionObjOutput = [];
|
||||
late double width;
|
||||
late double height;
|
||||
|
||||
final numberOptions = [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14",
|
||||
"15",
|
||||
"16",
|
||||
"17",
|
||||
"18",
|
||||
"19",
|
||||
"20",
|
||||
"21",
|
||||
"22",
|
||||
"23",
|
||||
"24",
|
||||
"25",
|
||||
"26",
|
||||
"27",
|
||||
"28",
|
||||
"29",
|
||||
"30"
|
||||
];
|
||||
|
||||
Future<void> generatePerscription() async {
|
||||
//start loading circle
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
|
||||
var response1 = await http.post(
|
||||
Uri.parse("${AppEnviroment.baseApiUrl}/minio/generate/perscription/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
"app_id": widget.selectedPatient.app_id,
|
||||
"fullName":
|
||||
"${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}",
|
||||
"id_no": widget.selectedPatient.id_no,
|
||||
"docfname":
|
||||
"DR. ${widget.signedInUser.fname} ${widget.signedInUser.lname}",
|
||||
"busName": widget.business!.Name,
|
||||
"busAddr": "*TO BE ADDED IN THE FUTURE*",
|
||||
"busNo": widget.business!.contact_no,
|
||||
"busEmail": widget.business!.bus_email,
|
||||
"logo_path": widget.business!.logo_path,
|
||||
"sig_path": widget.businessUser!.sig_path,
|
||||
"data": perscriptionObjOutput,
|
||||
}),
|
||||
);
|
||||
//print(response1.statusCode);
|
||||
DateTime now = new DateTime.now();
|
||||
DateTime date = new DateTime(now.year, now.month, now.day);
|
||||
String fileName =
|
||||
"Perscription-${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}-${date.toString().substring(0, 10)}.pdf";
|
||||
if (response1.statusCode == 200) {
|
||||
var response2 = await http.post(
|
||||
Uri.parse("${AppEnviroment.baseApiUrl}/files/insert/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
"file_path":
|
||||
"${widget.selectedPatient.app_id}/patient_files/$fileName",
|
||||
"file_name": fileName,
|
||||
"app_id": widget.selectedPatient.app_id
|
||||
}),
|
||||
);
|
||||
//print(response2.statusCode);
|
||||
if (response2.statusCode == 201) {
|
||||
setState(() {
|
||||
//To do
|
||||
widget.medicineController.clear();
|
||||
widget.dosageController.clear();
|
||||
widget.timesDailyController.clear();
|
||||
widget.noDaysController.clear();
|
||||
widget.timesDailyController.clear();
|
||||
widget.noRepeatsController.clear();
|
||||
widget.quantityController.clear();
|
||||
widget.outputController.clear();
|
||||
// futueFiles = fetchFiles();
|
||||
});
|
||||
// end loading circle
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pushNamed('/patient-manager/patient',
|
||||
arguments: PatientViewArguments(
|
||||
widget.signedInUser,
|
||||
widget.selectedPatient,
|
||||
widget.businessUser,
|
||||
widget.business,
|
||||
"business",
|
||||
));
|
||||
String message =
|
||||
"The perscription $fileName has been successfully generated and added to ${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}'s record. You can now access and download it for their use.";
|
||||
successPopUp(message);
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
} else {
|
||||
internetConnectionPopUp();
|
||||
}
|
||||
}
|
||||
|
||||
void internetConnectionPopUp() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Internet Connection");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void successPopUp(String message) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MIHSuccessMessage(
|
||||
successType: "Success",
|
||||
successMessage: message,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void getMedsPopUp(TextEditingController medSearch) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MedicineSearch(
|
||||
searchVlaue: medSearch,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
bool isFieldsFilled() {
|
||||
if (widget.medicineController.text.isEmpty ||
|
||||
// widget.quantityController.text.isEmpty ||
|
||||
widget.dosageController.text.isEmpty ||
|
||||
widget.timesDailyController.text.isEmpty ||
|
||||
widget.noDaysController.text.isEmpty ||
|
||||
widget.noRepeatsController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void updatePerscriptionList() {
|
||||
String name;
|
||||
String unit;
|
||||
String form;
|
||||
List<String> medNameList = widget.medicineController.text.split("%t");
|
||||
if (medNameList.length == 1) {
|
||||
name = medNameList[0];
|
||||
unit = "";
|
||||
form = "";
|
||||
} else {
|
||||
name = medNameList[0];
|
||||
unit = medNameList[1];
|
||||
form = medNameList[2];
|
||||
}
|
||||
int quantityCalc = calcQuantity(
|
||||
widget.dosageController.text,
|
||||
widget.timesDailyController.text,
|
||||
widget.noDaysController.text,
|
||||
medNameList[2].toLowerCase());
|
||||
Perscription tempObj = Perscription(
|
||||
name: name,
|
||||
unit: unit,
|
||||
form: form,
|
||||
fullForm: getFullDoagesForm(form),
|
||||
quantity: "$quantityCalc",
|
||||
dosage: widget.dosageController.text,
|
||||
times: widget.timesDailyController.text,
|
||||
days: widget.noDaysController.text,
|
||||
repeats: widget.noRepeatsController.text,
|
||||
);
|
||||
perscriptionObjOutput.add(tempObj);
|
||||
}
|
||||
|
||||
String getPerscTitle(int index) {
|
||||
return "${perscriptionObjOutput[index].name} - ${perscriptionObjOutput[index].form}";
|
||||
}
|
||||
|
||||
String getPerscSubtitle(int index) {
|
||||
if (perscriptionObjOutput[index].form.toLowerCase() == "syr") {
|
||||
String unit = perscriptionObjOutput[index].unit.toLowerCase();
|
||||
if (perscriptionObjOutput[index].unit.toLowerCase().contains("ml")) {
|
||||
unit = "ml";
|
||||
}
|
||||
return "${perscriptionObjOutput[index].dosage} $unit, ${perscriptionObjOutput[index].times} time(s) daily, for ${perscriptionObjOutput[index].days} day(s)\nQuantity: ${perscriptionObjOutput[index].quantity}\nNo. of repeats: ${perscriptionObjOutput[index].repeats}";
|
||||
} else {
|
||||
return "${perscriptionObjOutput[index].dosage} ${perscriptionObjOutput[index].fullForm}(s), ${perscriptionObjOutput[index].times} time(s) daily, for ${perscriptionObjOutput[index].days} day(s)\nQuantity: ${perscriptionObjOutput[index].quantity}\nNo. of repeats: ${perscriptionObjOutput[index].repeats}";
|
||||
}
|
||||
}
|
||||
|
||||
String getFullDoagesForm(String abr) {
|
||||
var dosageFormList = {
|
||||
"liq": "liquid",
|
||||
"tab": "tablet",
|
||||
"cap": "capsule",
|
||||
"cps": "capsule",
|
||||
"oin": "ointment",
|
||||
"lit": "lotion",
|
||||
"lot": "lotion",
|
||||
"inj": "injection",
|
||||
"syr": "syrup",
|
||||
"dsp": "effervescent tablet",
|
||||
"eft": "effervescent tablet",
|
||||
"ear": "drops",
|
||||
"drp": "drops",
|
||||
"opd": "drops",
|
||||
"udv": "vial",
|
||||
"sus": "suspension",
|
||||
"susp": "suspension",
|
||||
"cal": "calasthetic",
|
||||
"sol": "solution",
|
||||
"sln": "solution",
|
||||
"neb": "nebuliser",
|
||||
"inh": "inhaler",
|
||||
"spo": "inhaler",
|
||||
"inf": "infusion",
|
||||
"chg": "chewing Gum",
|
||||
"vac": "vacutainer",
|
||||
"vag": "vaginal gel",
|
||||
"jel": "gel",
|
||||
"eyo": "eye ointment",
|
||||
"vat": "vaginal cream",
|
||||
"poi": "injection",
|
||||
"ped": "powder",
|
||||
"pow": "powder",
|
||||
"por": "powder",
|
||||
"sac": "sachet",
|
||||
"sup": "suppository",
|
||||
"cre": "cream",
|
||||
"ptd": "patch",
|
||||
"ect": "tablet",
|
||||
"nas": "spray",
|
||||
};
|
||||
String form;
|
||||
if (dosageFormList[abr.toLowerCase()] == null) {
|
||||
form = abr;
|
||||
} else {
|
||||
form = dosageFormList[abr.toLowerCase()]!;
|
||||
}
|
||||
return form;
|
||||
}
|
||||
|
||||
int calcQuantity(String dosage, String times, String days, String form) {
|
||||
var dosageFormList = [
|
||||
"tab",
|
||||
"cap",
|
||||
"cps",
|
||||
"dsp",
|
||||
"eft",
|
||||
"udv",
|
||||
"chg",
|
||||
"sac",
|
||||
"sup",
|
||||
"ptd",
|
||||
"ect",
|
||||
];
|
||||
if (dosageFormList.contains(form)) {
|
||||
return int.parse(dosage) * int.parse(times) * int.parse(days);
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
Widget displayMedInput() {
|
||||
return Column(
|
||||
children: [
|
||||
KeyboardListener(
|
||||
focusNode: _focusNode,
|
||||
autofocus: true,
|
||||
onKeyEvent: (event) async {
|
||||
if (event is KeyDownEvent &&
|
||||
event.logicalKey == LogicalKeyboardKey.enter) {
|
||||
getMedsPopUp(widget.medicineController);
|
||||
}
|
||||
},
|
||||
child: SizedBox(
|
||||
width: 300,
|
||||
child: MIHSearchField(
|
||||
controller: widget.medicineController,
|
||||
hintText: "Medicine",
|
||||
required: true,
|
||||
editable: true,
|
||||
onTap: () {
|
||||
getMedsPopUp(widget.medicineController);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
// SizedBox(
|
||||
// width: 300,
|
||||
// child: MIHDropdownField(
|
||||
// controller: widget.quantityController,
|
||||
// hintText: "Quantity",
|
||||
// dropdownOptions: numberOptions,
|
||||
// required: true,
|
||||
// editable: true,
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(height: 10.0),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
child: MIHDropdownField(
|
||||
controller: widget.dosageController,
|
||||
hintText: "Dosage",
|
||||
dropdownOptions: numberOptions,
|
||||
required: true,
|
||||
editable: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
child: MIHDropdownField(
|
||||
controller: widget.timesDailyController,
|
||||
hintText: "Times Daily",
|
||||
dropdownOptions: numberOptions,
|
||||
required: true,
|
||||
editable: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
child: MIHDropdownField(
|
||||
controller: widget.noDaysController,
|
||||
hintText: "No. Days",
|
||||
dropdownOptions: numberOptions,
|
||||
required: true,
|
||||
editable: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
child: MIHDropdownField(
|
||||
controller: widget.noRepeatsController,
|
||||
hintText: "No. Repeats",
|
||||
dropdownOptions: numberOptions,
|
||||
required: true,
|
||||
editable: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30.0),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
height: 50,
|
||||
child: MIHButton(
|
||||
buttonText: "Add",
|
||||
buttonColor:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
textColor: MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
onTap: () {
|
||||
if (isFieldsFilled()) {
|
||||
// int quantity;
|
||||
// int.parse(widget.dosageController.text) *
|
||||
// int.parse(widget.timesDailyController.text) *
|
||||
// int.parse(widget.noDaysController.text);
|
||||
setState(() {
|
||||
//widget.quantityController.text = "$quantity";
|
||||
updatePerscriptionList();
|
||||
widget.medicineController.clear();
|
||||
widget.quantityController.clear();
|
||||
widget.dosageController.clear();
|
||||
widget.timesDailyController.clear();
|
||||
widget.noDaysController.clear();
|
||||
widget.noRepeatsController.clear();
|
||||
});
|
||||
|
||||
//addPatientAPICall();
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Input Error");
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget displayPerscList() {
|
||||
return Column(
|
||||
children: [
|
||||
Container(
|
||||
width: 550,
|
||||
height: 350,
|
||||
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: ListView.separated(
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Divider(),
|
||||
);
|
||||
},
|
||||
itemCount: perscriptionObjOutput.length,
|
||||
itemBuilder: (context, index) {
|
||||
//final patient = widget.patients[index].id_no.contains(widget.searchString);
|
||||
return ListTile(
|
||||
title: Text(
|
||||
getPerscTitle(index),
|
||||
style: TextStyle(
|
||||
color:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
getPerscSubtitle(index),
|
||||
style: TextStyle(
|
||||
color:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
),
|
||||
//onTap: () {},
|
||||
trailing: IconButton(
|
||||
icon: Icon(
|
||||
Icons.delete_forever_outlined,
|
||||
color:
|
||||
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
perscriptionObjOutput.removeAt(index);
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30.0),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
height: 50,
|
||||
child: MIHButton(
|
||||
onTap: () async {
|
||||
if (perscriptionObjOutput.isNotEmpty) {
|
||||
//print(jsonEncode(perscriptionObjOutput));
|
||||
await generatePerscription();
|
||||
Navigator.pop(context);
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const MIHErrorMessage(errorType: "Input Error");
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
buttonText: "Generate",
|
||||
buttonColor: MzanziInnovationHub.of(context)!.theme.successColor(),
|
||||
textColor: MzanziInnovationHub.of(context)!.theme.primaryColor(),
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
//futueMeds = getMedList(endpointMeds);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
setState(() {
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
});
|
||||
return Container(
|
||||
//width: ,
|
||||
height: (height / 3) * 1.5,
|
||||
child: SingleChildScrollView(
|
||||
child: Wrap(
|
||||
direction: Axis.horizontal,
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// mainAxisSize: MainAxisSize.max,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
displayMedInput(),
|
||||
displayPerscList(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user