From 927cd506c8ee6ca81ef3b3ae3b68caf429133090 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 3 Apr 2025 08:44:33 +0200 Subject: [PATCH] save for work later --- Frontend/lib/mih_apis/mih_user_apis.dart | 90 +++++++++++ Frontend/lib/mih_env/env.dart | 12 +- .../personal_profile/mzansi_profile.dart | 24 ++- .../package_tools/mih_personal_settings.dart | 147 ++++++++++++++++++ backend/routers/users.py | 9 +- 5 files changed, 267 insertions(+), 15 deletions(-) create mode 100644 Frontend/lib/mih_apis/mih_user_apis.dart create mode 100644 Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_settings.dart diff --git a/Frontend/lib/mih_apis/mih_user_apis.dart b/Frontend/lib/mih_apis/mih_user_apis.dart new file mode 100644 index 00000000..784c6a67 --- /dev/null +++ b/Frontend/lib/mih_apis/mih_user_apis.dart @@ -0,0 +1,90 @@ +import 'dart:convert'; + +import 'package:Mzansi_Innovation_Hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_pop_up_messages/mih_success_message.dart'; +import 'package:Mzansi_Innovation_Hub/mih_env/env.dart'; +import 'package:flutter/material.dart'; +import 'package:supertokens_flutter/http.dart' as http; +import 'package:supertokens_flutter/supertokens.dart'; + +class MihUserApis { + final baseAPI = AppEnviroment.baseApiUrl; + + static Future deleteAccount( + String app_id, + BuildContext context, + ) async { + loadingPopUp(context); + var response = await http.delete( + Uri.parse("${AppEnviroment.baseApiUrl}/user/delete/all/$app_id"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({"app_id": app_id}), + ); + + if (response.statusCode == 200) { + await SuperTokens.signOut(completionHandler: (error) { + print(error); + }); + if (await SuperTokens.doesSessionExist() == false) { + Navigator.of(context).pop(); + // Navigator.of(context).popAndPushNamed( + // '/', + // arguments: AuthArguments(true, false), + // ); + } + return true; + } else { + return false; + } + } + + // Future signOut() async { + // await SuperTokens.signOut(completionHandler: (error) { + // print(error); + // }); + // if (await SuperTokens.doesSessionExist() == false) { + // Navigator.of(context).pop(); + // Navigator.of(context).popAndPushNamed( + // '/', + // arguments: AuthArguments(true, false), + // ); + // } + // } + +//================== 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, + ); + }, + ); + } + + static void loadingPopUp(BuildContext context) { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle(); + }, + ); + } +} diff --git a/Frontend/lib/mih_env/env.dart b/Frontend/lib/mih_env/env.dart index c96e44e0..f86f1312 100644 --- a/Frontend/lib/mih_env/env.dart +++ b/Frontend/lib/mih_env/env.dart @@ -15,13 +15,13 @@ abstract class AppEnviroment { case Enviroment.dev: { //================= Android Dev Urls ================= - baseApiUrl = "http://10.0.2.2:8080"; - baseFileUrl = "http://10.0.2.2:9000"; - baseAiUrl = "http://10.0.2.2:11434"; + // baseApiUrl = "http://10.0.2.2:8080"; + // baseFileUrl = "http://10.0.2.2:9000"; + // baseAiUrl = "http://10.0.2.2:11434"; //================= Web Dev Urls ================= - // baseApiUrl = "http://localhost:8080"; - // baseFileUrl = "http://localhost:9000"; - // baseAiUrl = "http://localhost:11434"; + baseApiUrl = "http://localhost:8080"; + baseFileUrl = "http://localhost:9000"; + baseAiUrl = "http://localhost:11434"; whatsappAccessToken = "EAAPINXuNFdYBOzBjTcvZA2iPXEHbHRF9uNXyP3ihkPRUcBqKNru5g9NKRRKkFaiaITEzO3BMo6CjdUmlDH4qYTW2mzDrZB4Q21ZCEZBgECZCu27vfaOXJZCYQLNxwoXkrZBRYv8ZAP37f69r3z9JxLQxdxn9gwqA3oNZAlBBRapJQzxOr6pZBTdI3bbjbu17ZBIwRcF4JCqPDCNLEZCI3bmHwEd2i2niNMYZD"; //fingerPrintPluginKey = 'h5X7a5j14iUZCobI1ZeX'; diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart index d6da3b6b..46122c5c 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart @@ -1,8 +1,9 @@ -import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih_app.dart'; -import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih_app_action.dart'; -import 'package:Mzansi_Innovation_Hub/mih_components/mih_package/mih_app_tools.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_package_components/mih_app.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_package_components/mih_app_action.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_package_components/mih_app_tools.dart'; import 'package:Mzansi_Innovation_Hub/mih_objects/arguments.dart'; import 'package:Mzansi_Innovation_Hub/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart'; +import 'package:Mzansi_Innovation_Hub/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_settings.dart'; import 'package:flutter/material.dart'; class MzansiProfile extends StatefulWidget { @@ -51,6 +52,11 @@ class _MzansiProfileState extends State { _selcetedIndex = 0; }); }; + temp[const Icon(Icons.settings)] = () { + setState(() { + _selcetedIndex = 1; + }); + }; return MihAppTools( tools: temp, selcetedIndex: _selcetedIndex, @@ -58,11 +64,13 @@ class _MzansiProfileState extends State { } List getToolBody() { - List toolBodies = [ - MihPersonalProfile( - arguments: widget.arguments, - ), - ]; + List toolBodies = []; + toolBodies.add(MihPersonalProfile( + arguments: widget.arguments, + )); + toolBodies.add(MihPersonalSettings( + signedInUser: widget.arguments.signedInUser, + )); return toolBodies; } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_settings.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_settings.dart new file mode 100644 index 00000000..ddcac080 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_settings.dart @@ -0,0 +1,147 @@ +import 'package:Mzansi_Innovation_Hub/main.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_inputs_and_buttons/mih_button.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_layout/mih_single_child_scroll.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_package_components/mih-app_tool_body.dart'; +import 'package:Mzansi_Innovation_Hub/mih_components/mih_package_components/mih_app_alert.dart'; +import 'package:Mzansi_Innovation_Hub/mih_objects/app_user.dart'; +import 'package:flutter/material.dart'; + +class MihPersonalSettings extends StatefulWidget { + final AppUser signedInUser; + const MihPersonalSettings({ + super.key, + required this.signedInUser, + }); + + @override + State createState() => _MihPersonalSettingsState(); +} + +class _MihPersonalSettingsState extends State { + @override + Widget build(BuildContext context) { + return MihAppToolBody(borderOn: true, bodyItem: getBody()); + } + + void deleteAccountPopUp(BuildContext ctxtd) { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) { + return MihAppAlert( + alertIcon: Icon( + Icons.warning_amber_rounded, + size: 100, + color: MzanziInnovationHub.of(context)!.theme.errorColor(), + ), + alertTitle: + "Are you sure you want to permanently delete your MIH account?", + alertBody: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "This action will remove all of your data, and it cannot be recovered. We understand this is a big decision, so please take a moment to double-check.\n\nIf you're certain, please confirm below. If you've changed your mind, you can simply close this window.", + style: TextStyle( + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 15), + Wrap( + spacing: 10, + runSpacing: 10, + children: [ + SizedBox( + width: 300, + height: 50, + child: MIHButton( + onTap: () { + print("Delete account"); + }, + buttonText: "Delete", + buttonColor: + MzanziInnovationHub.of(context)!.theme.errorColor(), + textColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ), + SizedBox( + width: 300, + height: 50, + child: MIHButton( + onTap: () { + Navigator.pop(context); + }, + buttonText: "Cancel", + buttonColor: + MzanziInnovationHub.of(context)!.theme.successColor(), + textColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ), + ], + ) + ], + ), + alertColour: MzanziInnovationHub.of(context)!.theme.errorColor(), + ); + }, + ); + } + + Widget getBody() { + return MihSingleChildScroll( + child: Column( + children: [ + Text( + "Account Settings", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + Divider( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + const SizedBox(height: 30.0), + Wrap( + spacing: 10, + runSpacing: 10, + alignment: WrapAlignment.center, + crossAxisAlignment: WrapCrossAlignment.center, + children: [ + Text( + "Would you like to delete your MIH account?", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + SizedBox( + width: 300.0, + height: 50.0, + child: MIHButton( + buttonText: "Delete Account", + buttonColor: + MzanziInnovationHub.of(context)!.theme.errorColor(), + textColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + onTap: () { + deleteAccountPopUp(context); + }, + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/backend/routers/users.py b/backend/routers/users.py index ded17cb0..7e4d67d7 100644 --- a/backend/routers/users.py +++ b/backend/routers/users.py @@ -5,6 +5,8 @@ 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 supertokens_python.syncio import delete_user + from fastapi import Depends import database.dbConnection @@ -168,9 +170,14 @@ async def delete_users_data_by_app_id(app_id: str, session: SessionContainer = D "DELETE FROM patient_manager.claim_statement_file where app_id = %s", "DELETE FROM app_data.users where app_id = %s", ] - + #delete user from all tables for query in queries: cursor.execute(query, (app_id,)) + # Delete user from SuperTokens + try: + delete_user(app_id) + except Exception as error: + raise HTTPException(status_code=500, detail="Failed to delete user from SuperTokens - " + str(error)) db.commit() except Exception as error: db.rollback()