diff --git a/Frontend/images/loyalty_cards/Clicks_Club.png b/Frontend/images/loyalty_cards/Clicks_Club.png new file mode 100644 index 00000000..c6f22e50 Binary files /dev/null and b/Frontend/images/loyalty_cards/Clicks_Club.png differ diff --git a/Frontend/images/loyalty_cards/bb_club.png b/Frontend/images/loyalty_cards/bb_club.png new file mode 100644 index 00000000..ff7d03e0 Binary files /dev/null and b/Frontend/images/loyalty_cards/bb_club.png differ diff --git a/Frontend/images/loyalty_cards/dischem_benefit.png b/Frontend/images/loyalty_cards/dischem_benefit.png new file mode 100644 index 00000000..0130f30d Binary files /dev/null and b/Frontend/images/loyalty_cards/dischem_benefit.png differ diff --git a/Frontend/images/loyalty_cards/pnp_smart.png b/Frontend/images/loyalty_cards/pnp_smart.png new file mode 100644 index 00000000..6c232c74 Binary files /dev/null and b/Frontend/images/loyalty_cards/pnp_smart.png differ diff --git a/Frontend/images/loyalty_cards/spar_rewards.png b/Frontend/images/loyalty_cards/spar_rewards.png new file mode 100644 index 00000000..04dad579 Binary files /dev/null and b/Frontend/images/loyalty_cards/spar_rewards.png differ diff --git a/Frontend/images/loyalty_cards/wrewards.png b/Frontend/images/loyalty_cards/wrewards.png new file mode 100644 index 00000000..3822997b Binary files /dev/null and b/Frontend/images/loyalty_cards/wrewards.png differ diff --git a/Frontend/images/loyalty_cards/xtraSavings.png b/Frontend/images/loyalty_cards/xtraSavings.png new file mode 100644 index 00000000..8faa5b04 Binary files /dev/null and b/Frontend/images/loyalty_cards/xtraSavings.png differ diff --git a/Frontend/lib/mih_apis/mih_mzansi_wallet_apis.dart b/Frontend/lib/mih_apis/mih_mzansi_wallet_apis.dart new file mode 100644 index 00000000..3b64825c --- /dev/null +++ b/Frontend/lib/mih_apis/mih_mzansi_wallet_apis.dart @@ -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. + static Future> 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 patientQueue = List.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 deleteLoyaltyCardAPICall( + AppUser signedInUser, + int idloyalty_cards, + BuildContext context, + ) async { + var response = await http.delete( + Uri.parse( + "${AppEnviroment.baseApiUrl}/mzasni-wallet/loyalty-cards/delete/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({"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 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: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "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, + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_components/mih_inputs_and_buttons/mih_dropdown_input.dart b/Frontend/lib/mih_components/mih_inputs_and_buttons/mih_dropdown_input.dart index d906df54..07a715c0 100644 --- a/Frontend/lib/mih_components/mih_inputs_and_buttons/mih_dropdown_input.dart +++ b/Frontend/lib/mih_components/mih_inputs_and_buttons/mih_dropdown_input.dart @@ -6,7 +6,7 @@ class MIHDropdownField extends StatefulWidget { final String hintText; final bool required; final List 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 { setState(() { startup = false; }); + // widget.onSelect; } String? get _errorText { @@ -124,10 +125,8 @@ class _MIHDropdownFieldState extends State { errorText: _errorText, focusNode: _focus, - onSelected: (_) { - setState(() { - startup = false; - }); + onSelected: (selected) { + _onFocusChange(); // if (widget.editable == false) { // return false; // } diff --git a/Frontend/lib/mih_objects/loyalty_card.dart b/Frontend/lib/mih_objects/loyalty_card.dart new file mode 100644 index 00000000..a5a137df --- /dev/null +++ b/Frontend/lib/mih_objects/loyalty_card.dart @@ -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 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'), + }; + } +} diff --git a/Frontend/lib/mih_packages/mih_home/mih_home.dart b/Frontend/lib/mih_packages/mih_home/mih_home.dart index a5619512..19323030 100644 --- a/Frontend/lib/mih_packages/mih_home/mih_home.dart +++ b/Frontend/lib/mih_packages/mih_home/mih_home.dart @@ -137,6 +137,29 @@ class _MIHHomeState extends State { 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 { p: getPrim(), s: getSec(), )); + tileList.add(MIHTile( videoID: "hbKhlmY_56U", onTap: () { diff --git a/Frontend/lib/mih_packages/mzansi_wallet/builder/build_loyalty_card_list.dart b/Frontend/lib/mih_packages/mzansi_wallet/builder/build_loyalty_card_list.dart new file mode 100644 index 00000000..eea90871 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_wallet/builder/build_loyalty_card_list.dart @@ -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 cardList; + const BuildLoyaltyCardList({ + super.key, + required this.signedInUser, + required this.cardList, + }); + + @override + State createState() => _BuildLoyaltyCardListState(); +} + +class _BuildLoyaltyCardListState extends State { + 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, + ), + ), + ); + } + } +} diff --git a/Frontend/lib/mih_packages/mzansi_wallet/components/mih_card_display.dart b/Frontend/lib/mih_packages/mzansi_wallet/components/mih_card_display.dart new file mode 100644 index 00000000..c7d37ebe --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_wallet/components/mih_card_display.dart @@ -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 createState() => _MihCardDisplayState(); +} + +class _MihCardDisplayState extends State { + 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(); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_wallet/loyalty_cards.dart b/Frontend/lib/mih_packages/mzansi_wallet/loyalty_cards.dart new file mode 100644 index 00000000..1541fbef --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_wallet/loyalty_cards.dart @@ -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 createState() => _LoyaltyCardsState(); +} + +class _LoyaltyCardsState extends State { + final TextEditingController shopController = TextEditingController(); + final TextEditingController cardNumberController = TextEditingController(); + late Future> cardList; + //bool showSelectedCardType = false; + final ValueNotifier 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"), + ); + } + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_wallet/mzansi_wallet.dart b/Frontend/lib/mih_packages/mzansi_wallet/mzansi_wallet.dart new file mode 100644 index 00000000..02089d2e --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_wallet/mzansi_wallet.dart @@ -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 createState() => _MzansiWalletState(); +} + +class _MzansiWalletState extends State { + 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 {}, + ); + } +} diff --git a/Frontend/lib/mih_packages/patient_profile/patient_add.dart b/Frontend/lib/mih_packages/patient_profile/patient_add.dart index 1cf41ebc..fe7426cb 100644 --- a/Frontend/lib/mih_packages/patient_profile/patient_add.dart +++ b/Frontend/lib/mih_packages/patient_profile/patient_add.dart @@ -46,11 +46,12 @@ class _AddPatientState extends State { final baseAPI = AppEnviroment.baseApiUrl; late int futureDocOfficeId; - late bool medRequired; + //late bool medRequired; + final ValueNotifier 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 { 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 { 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 { medSchemeController.dispose(); addressController.dispose(); medAidController.dispose(); + medAidCodeController.removeListener(isRequired); + medRequired.dispose(); medMainMemController.dispose(); medAidCodeController.dispose(); _focusNode.dispose(); diff --git a/Frontend/lib/mih_packages/patient_profile/patient_edit.dart b/Frontend/lib/mih_packages/patient_profile/patient_edit.dart index 542aed2a..0cc58096 100644 --- a/Frontend/lib/mih_packages/patient_profile/patient_edit.dart +++ b/Frontend/lib/mih_packages/patient_profile/patient_edit.dart @@ -53,7 +53,8 @@ class _EditPatientState extends State { late int futureDocOfficeId; late String userEmail; - late bool medRequired; + // bool medRequired = false; + final ValueNotifier medRequired = ValueNotifier(false); late double width; late double height; @@ -324,7 +325,7 @@ class _EditPatientState extends State { } 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 { } 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 { 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 { void submitForm() { if (isFieldsFilled()) { - if (!medRequired) { + if (!medRequired.value) { setState(() { medMainMemController.text = ""; medNoController.text = ""; @@ -611,8 +615,10 @@ class _EditPatientState extends State { 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 { 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(); diff --git a/Frontend/lib/mih_packages/patient_profile/patient_view.dart b/Frontend/lib/mih_packages/patient_profile/patient_view.dart index 690d81fb..73de67d2 100644 --- a/Frontend/lib/mih_packages/patient_profile/patient_view.dart +++ b/Frontend/lib/mih_packages/patient_profile/patient_view.dart @@ -275,81 +275,5 @@ class _PatientViewState extends State { 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), - // ), - // ) - // ], - // ), - // ), - // ), - // ); } } diff --git a/Frontend/lib/mih_router/routeGenerator.dart b/Frontend/lib/mih_router/routeGenerator.dart index 706ca6ae..e56f1a1d 100644 --- a/Frontend/lib/mih_router/routeGenerator.dart +++ b/Frontend/lib/mih_router/routeGenerator.dart @@ -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) { diff --git a/Frontend/pubspec.lock b/Frontend/pubspec.lock index 7508278b..51a4ed8c 100644 --- a/Frontend/pubspec.lock +++ b/Frontend/pubspec.lock @@ -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" diff --git a/Frontend/pubspec.yaml b/Frontend/pubspec.yaml index 77eabcc1..e689fdff 100644 --- a/Frontend/pubspec.yaml +++ b/Frontend/pubspec.yaml @@ -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 diff --git a/Frontend/windows/flutter/generated_plugin_registrant.cc b/Frontend/windows/flutter/generated_plugin_registrant.cc index 7f895ee0..9543c80d 100644 --- a/Frontend/windows/flutter/generated_plugin_registrant.cc +++ b/Frontend/windows/flutter/generated_plugin_registrant.cc @@ -9,9 +9,11 @@ #include #include #include +#include #include #include #include +#include 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")); } diff --git a/Frontend/windows/flutter/generated_plugins.cmake b/Frontend/windows/flutter/generated_plugins.cmake index 268cd657..48a3185b 100644 --- a/Frontend/windows/flutter/generated_plugins.cmake +++ b/Frontend/windows/flutter/generated_plugins.cmake @@ -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 diff --git a/backend/database/dbConnection.py b/backend/database/dbConnection.py index fb1405fb..75686c36 100644 --- a/backend/database/dbConnection.py +++ b/backend/database/dbConnection.py @@ -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", diff --git a/backend/main.py b/backend/main.py index 7f5886cd..2dda05e9 100644 --- a/backend/main.py +++ b/backend/main.py @@ -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"]) diff --git a/backend/routers/mzansi_wallet.py b/backend/routers/mzansi_wallet.py new file mode 100644 index 00000000..e4ca2d8d --- /dev/null +++ b/backend/routers/mzansi_wallet.py @@ -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"} \ No newline at end of file