Merge pull request #7 from yaso-meth/New-Tile-Mzansi-Wallet

New-Tile-Mzansi-Wallet
This commit is contained in:
yaso-meth
2024-11-25 12:41:47 +02:00
committed by GitHub
26 changed files with 1262 additions and 224 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@@ -0,0 +1,178 @@
import 'dart:convert';
import 'package:Mzansi_Innovation_Hub/mih_objects/app_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/loyalty_card.dart';
import 'package:flutter/material.dart';
// import '../mih_components/mih_pop_up_messages/mih_error_message.dart';
// import '../mih_components/mih_pop_up_messages/mih_success_message.dart';
// import '../mih_env/env.dart';
// import '../mih_objects/app_user.dart';
// import '../mih_objects/arguments.dart';
// import '../mih_objects/business.dart';
// import '../mih_objects/business_user.dart';
// import '../mih_objects/notification.dart';
// import '../mih_objects/patient_access.dart';
// import '../mih_objects/patient_queue.dart';
// import '../mih_objects/patients.dart';
import 'package:supertokens_flutter/http.dart' as http;
import '../mih_components/mih_pop_up_messages/mih_error_message.dart';
import '../mih_components/mih_pop_up_messages/mih_success_message.dart';
import '../mih_env/env.dart';
class MIHMzansiWalletApis {
final baseAPI = AppEnviroment.baseApiUrl;
/// This function is used to fetch a list of loyalty cards for a user.
///
/// Patameters: app_id .
///
/// Returns List<PatientQueue>.
static Future<List<MIHLoyaltyCard>> getLoyaltyCards(
String app_id,
) async {
//print("Patien manager page: $endpoint");
final response = await http.get(Uri.parse(
"${AppEnviroment.baseApiUrl}/mzasni-wallet/loyalty-cards/$app_id"));
// print("Here");
// print("Body: ${response.body}");
// print("Code: ${response.statusCode}");
// errorCode = response.statusCode.toString();
// errorBody = response.body;
if (response.statusCode == 200) {
//print("Here1");
Iterable l = jsonDecode(response.body);
//print("Here2");
List<MIHLoyaltyCard> patientQueue = List<MIHLoyaltyCard>.from(
l.map((model) => MIHLoyaltyCard.fromJson(model)));
//print("Here3");
//print(patientQueue);
return patientQueue;
} else {
throw Exception('failed to fatch loyalty cards');
}
}
/// This function is used to Delete loyalty card from users mzansi wallet.
///
/// Patameters:-
/// AppUser signedInUser,
/// int idloyalty_cards,
/// BuildContext context,
///
/// Returns VOID (TRIGGERS NOTIGICATIOPN ON SUCCESS)
static Future<void> deleteLoyaltyCardAPICall(
AppUser signedInUser,
int idloyalty_cards,
BuildContext context,
) async {
var response = await http.delete(
Uri.parse(
"${AppEnviroment.baseApiUrl}/mzasni-wallet/loyalty-cards/delete/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{"idloyalty_cards": idloyalty_cards}),
);
//print("Here4");
//print(response.statusCode);
if (response.statusCode == 200) {
Navigator.of(context).pop();
Navigator.of(context).pop();
Navigator.of(context).pushNamed(
'/mzansi-wallet',
arguments: signedInUser,
);
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, context);
} else {
internetConnectionPopUp(context);
}
}
/// This function is used to add a lopyalty card to users mzansi wallet.
///
/// Patameters:-
/// AppUser signedInUser,
/// String app_id,
/// String shop_name,
/// String card_number,
/// BuildContext context,
///
/// Returns VOID (TRIGGERS SUCCESS pop up)
static Future<void> addLoyaltyCardAPICall(
AppUser signedInUser,
String app_id,
String shop_name,
String card_number,
BuildContext context,
) async {
var response = await http.post(
Uri.parse(
"${AppEnviroment.baseApiUrl}/mzasni-wallet/loyalty-cards/insert/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"app_id": app_id,
"shop_name": shop_name,
"card_number": card_number,
}),
);
if (response.statusCode == 201) {
// Navigator.pushNamed(context, '/patient-manager/patient',
// arguments: widget.signedInUser);
String message =
"Your $shop_name Loyalty Card was successfully added to you Mzansi Wallet.";
Navigator.pop(context);
Navigator.pop(context);
Navigator.of(context).pushNamed(
'/mzansi-wallet',
arguments: signedInUser,
);
// 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, context);
} else {
internetConnectionPopUp(context);
}
}
//================== POP UPS ==========================================================================
static void internetConnectionPopUp(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(
errorType: "Internet Connection",
);
},
);
}
static void successPopUp(String message, BuildContext context) {
showDialog(
context: context,
builder: (context) {
return MIHSuccessMessage(
successType: "Success",
successMessage: message,
);
},
);
}
}

View File

@@ -6,7 +6,7 @@ class MIHDropdownField extends StatefulWidget {
final String hintText;
final bool required;
final List<String> dropdownOptions;
final void Function(String?)? onSelect;
// final void Function(String?)? onSelect;
final bool editable;
const MIHDropdownField({
@@ -16,7 +16,7 @@ class MIHDropdownField extends StatefulWidget {
required this.dropdownOptions,
required this.required,
required this.editable,
this.onSelect,
// this.onSelect,
});
@override
@@ -59,6 +59,7 @@ class _MIHDropdownFieldState extends State<MIHDropdownField> {
setState(() {
startup = false;
});
// widget.onSelect;
}
String? get _errorText {
@@ -124,10 +125,8 @@ class _MIHDropdownFieldState extends State<MIHDropdownField> {
errorText: _errorText,
focusNode: _focus,
onSelected: (_) {
setState(() {
startup = false;
});
onSelected: (selected) {
_onFocusChange();
// if (widget.editable == false) {
// return false;
// }

View File

@@ -0,0 +1,31 @@
class MIHLoyaltyCard {
final int idloyalty_cards;
final String app_id;
final String shop_name;
final String card_number;
const MIHLoyaltyCard({
required this.idloyalty_cards,
required this.app_id,
required this.shop_name,
required this.card_number,
});
factory MIHLoyaltyCard.fromJson(Map<String, dynamic> json) {
return switch (json) {
{
"idloyalty_cards": int idloyalty_cards,
"app_id": String app_id,
"shop_name": String shop_name,
"card_number": String card_number,
} =>
MIHLoyaltyCard(
idloyalty_cards: idloyalty_cards,
app_id: app_id,
shop_name: shop_name,
card_number: card_number,
),
_ => throw const FormatException('Failed to load loyalty card objects'),
};
}
}

View File

@@ -137,6 +137,29 @@ class _MIHHomeState extends State<MIHHome> {
p: getPrim(),
s: getSec(),
));
tileList.add(MIHTile(
onTap: () {
Navigator.of(context).pushNamed(
'/mzansi-wallet',
arguments: widget.signedInUser,
);
},
tileName: "Mzansi Wallet",
tileIcon: Center(
child: FaIcon(
FontAwesomeIcons.wallet,
color: getSec(),
size: 200,
),
),
// Icon(
// Icons.info_outline,
// color: getSec(),
// size: 230,
// ),
p: getPrim(),
s: getSec(),
));
tileList.add(MIHTile(
videoID: "NUDdoWrbXNc",
onTap: () {
@@ -206,6 +229,7 @@ class _MIHHomeState extends State<MIHHome> {
p: getPrim(),
s: getSec(),
));
tileList.add(MIHTile(
videoID: "hbKhlmY_56U",
onTap: () {

View File

@@ -0,0 +1,119 @@
import 'package:Mzansi_Innovation_Hub/main.dart';
import 'package:Mzansi_Innovation_Hub/mih_apis/mih_mzansi_wallet_apis.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_window.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/app_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/loyalty_card.dart';
import 'package:Mzansi_Innovation_Hub/mih_packages/mzansi_wallet/components/mih_card_display.dart';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_barcodes/barcodes.dart';
class BuildLoyaltyCardList extends StatefulWidget {
final AppUser signedInUser;
final List<MIHLoyaltyCard> cardList;
const BuildLoyaltyCardList({
super.key,
required this.signedInUser,
required this.cardList,
});
@override
State<BuildLoyaltyCardList> createState() => _BuildLoyaltyCardListState();
}
class _BuildLoyaltyCardListState extends State<BuildLoyaltyCardList> {
void viewCardWindow(int index) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MIHWindow(
fullscreen: false,
windowTitle: widget.cardList[index].shop_name.toUpperCase(),
windowTools: [
IconButton(
onPressed: () {
MIHMzansiWalletApis.deleteLoyaltyCardAPICall(
widget.signedInUser,
widget.cardList[index].idloyalty_cards,
context,
);
},
icon: Icon(
Icons.delete,
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
),
],
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MihCardDisplay(
shopName: widget.cardList[index].shop_name, height: 250),
],
),
const SizedBox(height: 15),
SizedBox(
height: 150,
child:
SfBarcodeGenerator(value: widget.cardList[index].card_number),
),
Text(
"Card Number: ${widget.cardList[index].card_number}",
style: TextStyle(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
),
),
],
),
);
}
@override
Widget build(BuildContext context) {
if (widget.cardList.isNotEmpty) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, int index) {
return Divider(
color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
);
},
itemCount: widget.cardList.length,
itemBuilder: (context, index) {
return ListTile(
title: MihCardDisplay(
shopName: widget.cardList[index].shop_name, height: 200),
// subtitle: Text(
// "Card Number: ${widget.cardList[index].card_number}",
// style: TextStyle(
// color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
// ),
// ),
// trailing: Icon(
// Icons.arrow_forward,
// color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
// ),
onTap: () {
viewCardWindow(index);
},
);
},
);
} else {
return const Padding(
padding: EdgeInsets.only(top: 25.0),
child: Center(
child: Text(
"No Cards Available",
style: TextStyle(fontSize: 25, color: Colors.grey),
textAlign: TextAlign.center,
),
),
);
}
}
}

View File

@@ -0,0 +1,101 @@
import 'package:flutter/material.dart';
class MihCardDisplay extends StatefulWidget {
final String shopName;
final double height;
const MihCardDisplay({
super.key,
required this.shopName,
required this.height,
});
@override
State<MihCardDisplay> createState() => _MihCardDisplayState();
}
class _MihCardDisplayState extends State<MihCardDisplay> {
Widget displayLoyaltyCard() {
switch (widget.shopName.toLowerCase()) {
case "best before":
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: widget.height,
child: Image.asset('images/loyalty_cards/bb_club.png'),
),
],
);
case "checkers":
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: widget.height,
child: Image.asset('images/loyalty_cards/xtraSavings.png'),
),
],
);
case "clicks":
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: widget.height,
child: Image.asset('images/loyalty_cards/Clicks_Club.png'),
),
],
);
case "dis-chem":
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: widget.height,
child: Image.asset('images/loyalty_cards/dischem_benefit.png'),
),
],
);
case "pick n pay":
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: widget.height,
child: Image.asset('images/loyalty_cards/pnp_smart.png'),
),
],
);
case "spar":
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: widget.height,
child: Image.asset('images/loyalty_cards/spar_rewards.png'),
),
],
);
case "woolworths":
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: widget.height,
child: Image.asset('images/loyalty_cards/wrewards.png'),
),
],
);
default:
return const SizedBox(
height: 150,
//child: Placeholder(),
);
}
}
@override
Widget build(BuildContext context) {
return displayLoyaltyCard();
}
}

View File

@@ -0,0 +1,237 @@
import 'package:Mzansi_Innovation_Hub/main.dart';
import 'package:Mzansi_Innovation_Hub/mih_apis/mih_mzansi_wallet_apis.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_button.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_dropdown_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_text_input.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_window.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/app_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/loyalty_card.dart';
import 'package:Mzansi_Innovation_Hub/mih_packages/mzansi_wallet/builder/build_loyalty_card_list.dart';
import 'package:Mzansi_Innovation_Hub/mih_packages/mzansi_wallet/components/mih_card_display.dart';
import 'package:flutter/material.dart';
import 'package:simple_barcode_scanner/simple_barcode_scanner.dart';
class LoyaltyCards extends StatefulWidget {
final AppUser signedInUser;
const LoyaltyCards({
super.key,
required this.signedInUser,
});
@override
State<LoyaltyCards> createState() => _LoyaltyCardsState();
}
class _LoyaltyCardsState extends State<LoyaltyCards> {
final TextEditingController shopController = TextEditingController();
final TextEditingController cardNumberController = TextEditingController();
late Future<List<MIHLoyaltyCard>> cardList;
//bool showSelectedCardType = false;
final ValueNotifier<String> shopName = ValueNotifier("");
void addCardWindow() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MIHWindow(
fullscreen: false,
windowTitle: "Add New Loyalty Card",
windowTools: const [
SizedBox(width: 35),
// IconButton(
// onPressed: () {
// //Delete card API Call
// },
// icon: Icon(
// Icons.delete,
// color: MzanziInnovationHub.of(context)!.theme.secondaryColor(),
// ),
// ),
],
onWindowTapClose: () {
shopController.clear();
cardNumberController.clear();
shopName.value = "";
Navigator.pop(context);
},
windowBody: [
MIHDropdownField(
controller: shopController,
hintText: "Shop Name",
dropdownOptions: const [
"Best Before",
"Checkers",
"Clicks",
"Dis-Chem",
"Pick n Pay",
"Spar",
"Woolworths"
],
required: true,
editable: true,
),
ValueListenableBuilder(
valueListenable: shopName,
builder: (BuildContext context, String value, Widget? child) {
return Visibility(
visible: value != "",
child: Column(
children: [
const SizedBox(height: 10),
MihCardDisplay(shopName: shopName.value, height: 200),
],
),
);
},
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Flexible(
child: MIHTextField(
controller: cardNumberController,
hintText: "Card Number",
editable: true,
required: true,
),
),
const SizedBox(width: 10),
MIHButton(
onTap: () async {
String? res = await SimpleBarcodeScanner.scanBarcode(
context,
barcodeAppBar: const BarcodeAppBar(
appBarTitle: 'Scan Barcode',
centerTitle: false,
enableBackButton: true,
backButtonIcon: Icon(Icons.arrow_back),
),
isShowFlashIcon: true,
delayMillis: 500,
cameraFace: CameraFace.back,
scanFormat: ScanFormat.ALL_FORMATS,
);
setState(() {
cardNumberController.text = res as String;
});
},
buttonText: "Scan",
buttonColor:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
textColor:
MzanziInnovationHub.of(context)!.theme.primaryColor(),
),
],
),
const SizedBox(height: 15),
SizedBox(
width: 300,
height: 50,
child: MIHButton(
onTap: () {
MIHMzansiWalletApis.addLoyaltyCardAPICall(
widget.signedInUser,
widget.signedInUser.app_id,
shopController.text,
cardNumberController.text,
context,
);
},
buttonText: "Add",
buttonColor:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
textColor: MzanziInnovationHub.of(context)!.theme.primaryColor(),
),
),
],
),
);
}
void shopSelected() {
if (shopController.text.isNotEmpty) {
shopName.value = shopController.text;
} else {
shopName.value = "";
}
}
@override
void dispose() {
cardNumberController.dispose();
shopController.dispose();
shopController.removeListener(shopSelected);
shopName.dispose();
super.dispose();
}
@override
void initState() {
cardList = MIHMzansiWalletApis.getLoyaltyCards(widget.signedInUser.app_id);
shopController.addListener(shopSelected);
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: cardList,
builder: (context, snapshot) {
//print(snapshot.connectionState);
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: Mihloadingcircle(),
);
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
final cardList = snapshot.data!;
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"Loyalty Cards",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MzanziInnovationHub.of(context)!
.theme
.secondaryColor(),
),
),
IconButton(
icon: const Icon(Icons.add_card),
alignment: Alignment.topRight,
color:
MzanziInnovationHub.of(context)!.theme.secondaryColor(),
onPressed: () {
addCardWindow();
},
)
],
),
Divider(
color:
MzanziInnovationHub.of(context)!.theme.secondaryColor()),
const SizedBox(height: 10),
BuildLoyaltyCardList(
cardList: cardList,
signedInUser: widget.signedInUser,
)
],
);
} else {
return const Center(
child: Text("Error Loading Loyalty Cards"),
);
}
},
);
}
}

View File

@@ -0,0 +1,178 @@
import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_action.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_body.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_header.dart';
import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_layout_builder.dart';
import 'package:Mzansi_Innovation_Hub/mih_objects/app_user.dart';
import 'package:Mzansi_Innovation_Hub/mih_packages/mzansi_wallet/loyalty_cards.dart';
import 'package:flutter/material.dart';
class MzansiWallet extends StatefulWidget {
final AppUser signedInUser;
const MzansiWallet({
super.key,
required this.signedInUser,
});
@override
State<MzansiWallet> createState() => _MzansiWalletState();
}
class _MzansiWalletState extends State<MzansiWallet> {
int _selectedIndex = 0;
MIHAction getActionButton() {
return MIHAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
Navigator.of(context).pop();
Navigator.of(context).popAndPushNamed(
'/',
arguments: true,
);
},
);
}
MIHHeader getHeader() {
return const MIHHeader(
headerAlignment: MainAxisAlignment.center,
headerItems: [
Text(
"",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
],
);
}
MIHHeader getSecAction() {
return MIHHeader(
headerAlignment: MainAxisAlignment.end,
headerItems: [
//============ Patient Details ================
Visibility(
visible: _selectedIndex != 0,
child: IconButton(
onPressed: () {
setState(() {
_selectedIndex = 0;
});
},
icon: const Icon(
Icons.card_membership,
size: 35,
),
),
),
Visibility(
visible: _selectedIndex == 0,
child: IconButton.filled(
iconSize: 35,
onPressed: () {
setState(() {
_selectedIndex = 0;
});
},
icon: const Icon(
Icons.card_membership,
),
),
),
//============ Patient Notes ================
// Visibility(
// visible: _selectedIndex != 1,
// child: IconButton(
// onPressed: () {
// setState(() {
// _selectedIndex = 1;
// });
// },
// icon: const Icon(
// Icons.article_outlined,
// size: 35,
// ),
// ),
// ),
// Visibility(
// visible: _selectedIndex == 1,
// child: IconButton.filled(
// onPressed: () {
// setState(() {
// _selectedIndex = 1;
// });
// },
// icon: const Icon(
// Icons.article_outlined,
// size: 35,
// ),
// ),
// ),
// //============ Patient Files ================
// Visibility(
// visible: _selectedIndex != 2,
// child: IconButton(
// onPressed: () {
// setState(() {
// _selectedIndex = 2;
// });
// },
// icon: const Icon(
// Icons.file_present,
// size: 35,
// ),
// ),
// ),
// Visibility(
// visible: _selectedIndex == 2,
// child: IconButton.filled(
// onPressed: () {
// setState(() {
// _selectedIndex = 2;
// });
// },
// icon: const Icon(
// Icons.file_present,
// size: 35,
// ),
// ),
// ),
],
);
}
MIHBody getBody() {
return MIHBody(
borderOn: true,
bodyItems: [showSelection(_selectedIndex)],
);
}
Widget showSelection(int index) {
if (index == 0) {
return LoyaltyCards(signedInUser: widget.signedInUser);
} else if (index == 1) {
return const Placeholder();
} else {
return const Placeholder();
}
}
@override
Widget build(BuildContext context) {
return MIHLayoutBuilder(
actionButton: getActionButton(),
header: getHeader(),
secondaryActionButton: getSecAction(),
body: getBody(),
actionDrawer: null,
secondaryActionDrawer: null,
bottomNavBar: null,
pullDownToRefresh: false,
onPullDown: () async {},
);
}
}

View File

@@ -46,11 +46,12 @@ class _AddPatientState extends State<AddPatient> {
final baseAPI = AppEnviroment.baseApiUrl;
late int futureDocOfficeId;
late bool medRequired;
//late bool medRequired;
final ValueNotifier<bool> medRequired = ValueNotifier(false);
final FocusNode _focusNode = FocusNode();
bool isFieldsFilled() {
if (medRequired) {
if (medRequired.value) {
if (idController.text.isEmpty ||
fnameController.text.isEmpty ||
lnameController.text.isEmpty ||
@@ -151,13 +152,9 @@ class _AddPatientState extends State<AddPatient> {
void isRequired() {
//print("listerner triggered");
if (medAidController.text == "Yes") {
setState(() {
medRequired = true;
});
medRequired.value = true;
} else {
setState(() {
medRequired = false;
});
medRequired.value = false;
}
}
@@ -235,54 +232,59 @@ class _AddPatientState extends State<AddPatient> {
controller: medAidController,
hintText: "Medical Aid",
editable: true,
onSelect: (_) {
isRequired();
},
// 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"],
ValueListenableBuilder(
valueListenable: medRequired,
builder: (BuildContext context, bool value, Widget? child) {
return Visibility(
visible: value,
child: Column(
children: [
const SizedBox(height: 10.0),
MIHDropdownField(
controller: medMainMemController,
hintText: "Main Member",
editable: value,
required: value,
dropdownOptions: const ["Yes", "No"],
),
const SizedBox(height: 10.0),
MIHTextField(
controller: medNoController,
hintText: "Medical Aid No.",
editable: value,
required: value,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: medAidCodeController,
hintText: "Medical Aid Code",
editable: value,
required: value,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: medNameController,
hintText: "Medical Aid Name",
editable: value,
required: value,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: medSchemeController,
hintText: "Medical Aid Scheme",
editable: value,
required: value,
),
],
),
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(
@@ -372,6 +374,8 @@ class _AddPatientState extends State<AddPatient> {
medSchemeController.dispose();
addressController.dispose();
medAidController.dispose();
medAidCodeController.removeListener(isRequired);
medRequired.dispose();
medMainMemController.dispose();
medAidCodeController.dispose();
_focusNode.dispose();

View File

@@ -53,7 +53,8 @@ class _EditPatientState extends State<EditPatient> {
late int futureDocOfficeId;
late String userEmail;
late bool medRequired;
// bool medRequired = false;
final ValueNotifier<bool> medRequired = ValueNotifier(false);
late double width;
late double height;
@@ -324,7 +325,7 @@ class _EditPatientState extends State<EditPatient> {
}
bool isFieldsFilled() {
if (medRequired) {
if (medRequired.value) {
if (idController.text.isEmpty ||
fnameController.text.isEmpty ||
lnameController.text.isEmpty ||
@@ -357,15 +358,13 @@ class _EditPatientState extends State<EditPatient> {
}
void isRequired() {
//print("listerner triggered");
print("listerner triggered");
if (medAidController.text == "Yes") {
setState(() {
medRequired = true;
});
medRequired.value = true;
} else if (medAidController.text == "No") {
medRequired.value = false;
} else {
setState(() {
medRequired = false;
});
//print("here");
}
}
@@ -456,63 +455,68 @@ class _EditPatientState extends State<EditPatient> {
MIHDropdownField(
controller: medAidController,
hintText: "Medical Aid",
onSelect: (selected) {
if (selected == "Yes") {
setState(() {
medRequired = true;
});
} else {
setState(() {
medRequired = false;
});
}
},
// 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"],
ValueListenableBuilder(
valueListenable: medRequired,
builder: (BuildContext context, bool value, Widget? child) {
return Visibility(
visible: value,
child: Column(
children: [
const SizedBox(height: 10.0),
MIHDropdownField(
controller: medMainMemController,
hintText: "Main Member.",
editable: value,
required: value,
dropdownOptions: const ["Yes", "No"],
),
const SizedBox(height: 10.0),
MIHTextField(
controller: medNoController,
hintText: "Medical Aid No.",
editable: value,
required: value,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: medAidCodeController,
hintText: "Medical Aid Code",
editable: value,
required: value,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: medNameController,
hintText: "Medical Aid Name",
editable: value,
required: value,
),
const SizedBox(height: 10.0),
MIHTextField(
controller: medSchemeController,
hintText: "Medical Aid Scheme",
editable: value,
required: value,
),
],
),
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(
@@ -535,7 +539,7 @@ class _EditPatientState extends State<EditPatient> {
void submitForm() {
if (isFieldsFilled()) {
if (!medRequired) {
if (!medRequired.value) {
setState(() {
medMainMemController.text = "";
medNoController.text = "";
@@ -611,8 +615,10 @@ class _EditPatientState extends State<EditPatient> {
medSchemeController.dispose();
addressController.dispose();
medAidController.dispose();
medAidCodeController.removeListener(isRequired);
medMainMemController.dispose();
medAidCodeController.dispose();
medRequired.dispose();
_focusNode.dispose();
super.dispose();
}
@@ -622,29 +628,19 @@ class _EditPatientState extends State<EditPatient> {
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);
idController.text = widget.selectedPatient.id_no;
fnameController.text = widget.selectedPatient.first_name;
lnameController.text = widget.selectedPatient.last_name;
cellController.text = widget.selectedPatient.cell_no;
emailController.text = widget.selectedPatient.email;
medNameController.text = widget.selectedPatient.medical_aid_name;
medNoController.text = widget.selectedPatient.medical_aid_no;
medSchemeController.text = widget.selectedPatient.medical_aid_scheme;
addressController.text = widget.selectedPatient.address;
medAidController.text = widget.selectedPatient.medical_aid;
medMainMemController.text =
widget.selectedPatient.medical_aid_main_member;
medAidCodeController.text = widget.selectedPatient.medical_aid_code;
});
super.initState();

View File

@@ -275,81 +275,5 @@ class _PatientViewState extends State<PatientView> {
onPullDown: () async {},
),
);
// 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),
// ),
// )
// ],
// ),
// ),
// ),
// );
}
}

View File

@@ -1,3 +1,4 @@
import 'package:Mzansi_Innovation_Hub/mih_packages/mzansi_wallet/mzansi_wallet.dart';
import 'package:flutter/material.dart';
import '../mih_components/mih_layout/mih_print_prevew.dart';
import '../mih_components/mih_pop_up_messages/mih_notification_message.dart';
@@ -70,6 +71,7 @@ class RouteGenerator {
settings: settings, builder: (_) => const ForgotPassword());
//http://mzansi-innovation-hub.co.za/auth/reset-password
//===============================================================
//About MIH
case '/about':
return MaterialPageRoute(
@@ -157,6 +159,20 @@ class RouteGenerator {
return _errorRoute();
//===============================================================
// /mzansi wallet
case '/mzansi-wallet':
if (args is AppUser) {
//print("route generator: $args");
return MaterialPageRoute(
settings: settings,
builder: (_) => MzansiWallet(
signedInUser: args,
),
);
}
return _errorRoute();
//===============================================================
// Access Review Page
case '/access-review':
if (args is AppUser) {

View File

@@ -426,10 +426,10 @@ packages:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: "9ee02950848f61c4129af3d6ec84a1cfc0e47931abc746b03e7a3bc3e8ff6eda"
sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398"
url: "https://pub.dev"
source: hosted
version: "2.0.22"
version: "2.0.23"
flutter_swipe_detector:
dependency: "direct main"
description:
@@ -832,6 +832,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.4"
permission_handler:
dependency: transitive
description:
name: permission_handler
sha256: "18bf33f7fefbd812f37e72091a15575e72d5318854877e0e4035a24ac1113ecb"
url: "https://pub.dev"
source: hosted
version: "11.3.1"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
sha256: "71bbecfee799e65aff7c744761a57e817e73b738fedf62ab7afd5593da21f9f1"
url: "https://pub.dev"
source: hosted
version: "12.0.13"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
sha256: e6f6d73b12438ef13e648c4ae56bd106ec60d17e90a59c4545db6781229082a0
url: "https://pub.dev"
source: hosted
version: "9.4.5"
permission_handler_html:
dependency: transitive
description:
name: permission_handler_html
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
url: "https://pub.dev"
source: hosted
version: "0.1.3+5"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
sha256: e9c8eadee926c4532d0305dff94b85bf961f16759c3af791486613152af4b4f9
url: "https://pub.dev"
source: hosted
version: "4.2.3"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
url: "https://pub.dev"
source: hosted
version: "0.2.1"
petitparser:
dependency: transitive
description:
@@ -1016,6 +1064,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.0"
simple_barcode_scanner:
dependency: "direct main"
description:
name: simple_barcode_scanner
sha256: "993c4b0e22bbe6cf127f8e0001574fd54015b90e0698a058ec9fdb2fdf84bc55"
url: "https://pub.dev"
source: hosted
version: "0.2.5"
simple_gesture_detector:
dependency: transitive
description:
@@ -1125,6 +1181,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.6.1"
syncfusion_flutter_barcodes:
dependency: "direct main"
description:
name: syncfusion_flutter_barcodes
sha256: "5e65d005474caadfc48e0ecc5142da06f401900036631674a610a202b270be9d"
url: "https://pub.dev"
source: hosted
version: "26.2.10"
syncfusion_flutter_core:
dependency: "direct main"
description:
@@ -1361,10 +1425,10 @@ packages:
dependency: transitive
description:
name: web
sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
url: "https://pub.dev"
source: hosted
version: "1.0.0"
version: "1.1.0"
web_socket:
dependency: transitive
description:
@@ -1413,6 +1477,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.16.2"
webview_windows:
dependency: transitive
description:
name: webview_windows
sha256: "47fcad5875a45db29dbb5c9e6709bf5c88dcc429049872701343f91ed7255730"
url: "https://pub.dev"
source: hosted
version: "0.4.0"
win32:
dependency: transitive
description:
@@ -1478,5 +1550,5 @@ packages:
source: hosted
version: "3.1.0"
sdks:
dart: ">=3.5.0 <3.6.0"
dart: ">=3.5.3 <3.6.0"
flutter: ">=3.24.0"

View File

@@ -61,6 +61,8 @@ dependencies:
table_calendar: ^3.1.2
flutter_swipe_detector: ^2.0.0
youtube_player_iframe: ^5.2.0
syncfusion_flutter_barcodes: ^26.2.10
simple_barcode_scanner: ^0.2.5
dev_dependencies:
flutter_test:
@@ -90,6 +92,7 @@ flutter:
# To add assets to your application, add an assets section, like this:
assets:
- images/
- images/loyalty_cards/
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see

View File

@@ -9,9 +9,11 @@
#include <app_links/app_links_plugin_c_api.h>
#include <firebase_core/firebase_core_plugin_c_api.h>
#include <geolocator_windows/geolocator_windows.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
#include <printing/printing_plugin.h>
#include <syncfusion_pdfviewer_windows/syncfusion_pdfviewer_windows_plugin.h>
#include <url_launcher_windows/url_launcher_windows.h>
#include <webview_windows/webview_windows_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
AppLinksPluginCApiRegisterWithRegistrar(
@@ -20,10 +22,14 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
GeolocatorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("GeolocatorWindows"));
PermissionHandlerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
PrintingPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("PrintingPlugin"));
SyncfusionPdfviewerWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("SyncfusionPdfviewerWindowsPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
WebviewWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("WebviewWindowsPlugin"));
}

View File

@@ -6,9 +6,11 @@ list(APPEND FLUTTER_PLUGIN_LIST
app_links
firebase_core
geolocator_windows
permission_handler_windows
printing
syncfusion_pdfviewer_windows
url_launcher_windows
webview_windows
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

View File

@@ -24,6 +24,14 @@ def dbDataAccessConnect():
database="data_access"
)
def dbMzansiWalletConnect():
return mysql.connector.connect(
host="mysqldb",
user="root",
passwd="C@rtoon1995",
database="mzansi_wallet"
)
def dbAllConnect():
return mysql.connector.connect(
host="mysqldb",

View File

@@ -14,6 +14,7 @@ import routers.business_user as business_user
import routers.business as business
import routers.access_request as access_request
import routers.patient_access as patient_access
import routers.mzansi_wallet as mzansi_wallet
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware import Middleware
from supertokens_python import get_all_cors_headers
@@ -86,6 +87,7 @@ app.include_router(medicine.router)
app.include_router(business_user.router)
app.include_router(business.router)
app.include_router(notifications.router)
app.include_router(mzansi_wallet.router)
# Check if server is up
@app.get("/", tags=["Server Check"])

View File

@@ -0,0 +1,138 @@
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from datetime import date
#from ..database import dbConnection
import database
#SuperToken Auth from front end
from supertokens_python.recipe.session.framework.fastapi import verify_session
from supertokens_python.recipe.session import SessionContainer
from fastapi import Depends
router = APIRouter()
class LoyaltyCardDeleteRequest(BaseModel):
idloyalty_cards: int
class MzansiWalletInsertRequest(BaseModel):
app_id: str
shop_name: str
card_number: str
# class patientNoteUpdateRequest(BaseModel):
# idpatient_notes: int
# note_name: str
# note_text: str
# doc_office: str
# doctor: str
# patient_id: int
# Get List of all loyalty cards by user
@router.get("/mzasni-wallet/loyalty-cards/{app_id}", tags=["Mzansi Wallet"])
async def read_all_loyalty_cards_by_app_id(app_id: str, session: SessionContainer = Depends(verify_session())): # , session: SessionContainer = Depends(verify_session())
db = database.dbConnection.dbMzansiWalletConnect()
cursor = db.cursor()
query = "SELECT * FROM loyalty_cards where app_id = %s ORDER BY shop_name Asc"
cursor.execute(query, (app_id,))
items = [
{
"idloyalty_cards": item[0],
"app_id": item[1],
"shop_name": item[2],
"card_number": item[3],
}
for item in cursor.fetchall()
]
cursor.close()
db.close()
return items
# Get List of all notes by patient
# @router.get("/notes/patients-docOffice/", tags="patients_notes")
# async def read_all_patientsby(itemRequest: noteRequest, session: SessionContainer = Depends(verify_session())):
# db = database.dbConnection.dbPatientManagerConnect()
# cursor = db.cursor()
# query = "select patient_notes.idpatient_notes, patient_notes.note_name, patient_notes.note_text, patient_notes.patient_id, patient_notes.insert_date, patients.doc_office_id "
# query += "from patient_manager.patient_notes "
# query += "inner join patient_manager.patients "
# query += "on patient_notes.patient_id = patients.idpatients "
# query += "where patient_notes.patient_id = %s and patients.doc_office_id = %s"
# cursor.execute(query, (itemRequest.patientID, itemRequest.DocOfficeID,))
# items = [
# {
# "idpatient_notes": item[0],
# "note_name": item[1],
# "note_text": item[2],
# "insert_date": item[3],
# }
# for item in cursor.fetchall()
# ]
# cursor.close()
# db.close()
# return items
# Insert loyalty cards into table
@router.post("/mzasni-wallet/loyalty-cards/insert/", tags=["Mzansi Wallet"], status_code=201)
async def insert_loyalty_card(itemRequest : MzansiWalletInsertRequest): #, session: SessionContainer = Depends(verify_session())
db = database.dbConnection.dbMzansiWalletConnect()
cursor = db.cursor()
query = "insert into loyalty_cards "
query += "(app_id, shop_name, card_number) "
query += "values (%s, %s, %s)"
notetData = (itemRequest.app_id,
itemRequest.shop_name,
itemRequest.card_number,
)
try:
cursor.execute(query, notetData)
except Exception as error:
print(error)
raise HTTPException(status_code=404, detail="Failed to Create Record")
# return {"message": error}
db.commit()
cursor.close()
db.close()
return {"message": "Successfully Created Record"}
# Delete loyalty cards on table
@router.delete("/mzasni-wallet/loyalty-cards/delete/", tags=["Mzansi Wallet"])
async def Delete_loyalty_card(itemRequest : LoyaltyCardDeleteRequest, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session())
# today = date.today()
db = database.dbConnection.dbMzansiWalletConnect()
cursor = db.cursor()
query = "delete from loyalty_cards "
query += "where idloyalty_cards=%s"
# notetData = (itemRequest.idpatient_notes)
try:
cursor.execute(query, (str(itemRequest.idloyalty_cards),))
except Exception as error:
print(error)
raise HTTPException(status_code=404, detail="Failed to Delete Record")
#return {"query": query, "message": error}
db.commit()
cursor.close()
db.close()
return {"message": "Successfully deleted Record"}
# Update Patient note on table
# @router.put("/notes/update/", tags="patients_notes")
# async def UpdatePatient(itemRequest : patientNoteUpdateRequest, session: SessionContainer = Depends(verify_session())):
# today = date.today()
# db = database.dbConnection.dbPatientManagerConnect()
# cursor = db.cursor()
# query = "update patient_notes "
# query += "set note_name=%s, note_text=%s, patient_id=%s, insert_date=%s "
# query += "where idpatient_notes=%s"
# notetData = (itemRequest.note_name,
# itemRequest.note_text,
# itemRequest.patient_id,
# today,
# itemRequest.idpatient_notes)
# try:
# cursor.execute(query, notetData)
# except Exception as error:
# raise HTTPException(status_code=404, detail="Failed to Update Record")
# #return {"query": query, "message": error}
# db.commit()
# cursor.close()
# db.close()
# return {"message": "Successfully Updated Record"}