diff --git a/Frontend/android/app/build.gradle.kts b/Frontend/android/app/build.gradle.kts index ad4ac4c6..c96f5437 100644 --- a/Frontend/android/app/build.gradle.kts +++ b/Frontend/android/app/build.gradle.kts @@ -55,6 +55,11 @@ android { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig = signingConfigs.getByName("release") + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) } } } diff --git a/Frontend/android/app/proguard-rules.pro b/Frontend/android/app/proguard-rules.pro new file mode 100644 index 00000000..d216aea2 --- /dev/null +++ b/Frontend/android/app/proguard-rules.pro @@ -0,0 +1,5 @@ +# R8/ProGuard rules to prevent removal of necessary Facebook Infer annotations +-keep class com.facebook.infer.annotation.** { *; } +-keep interface com.facebook.infer.annotation.** { *; } +-dontwarn com.facebook.infer.annotation.Nullsafe$Mode +-dontwarn com.facebook.infer.annotation.Nullsafe \ No newline at end of file diff --git a/Frontend/android/app/src/main/AndroidManifest.xml b/Frontend/android/app/src/main/AndroidManifest.xml index 41e80cd2..6683a646 100644 --- a/Frontend/android/app/src/main/AndroidManifest.xml +++ b/Frontend/android/app/src/main/AndroidManifest.xml @@ -19,7 +19,8 @@ + android:icon="@mipmap/launcher_icon" + android:enableOnBackInvokedCallback="true"> 6.20.1.0) - Google-Mobile-Ads-SDK (12.2.0): - GoogleUserMessagingPlatform (>= 1.1) - google_mobile_ads (6.0.0): - Flutter - Google-Mobile-Ads-SDK (~> 12.2.0) - webview_flutter_wkwebview + - GoogleMobileAdsMediationFacebook (6.20.1.0): + - FBAudienceNetwork (= 6.20.1) + - Google-Mobile-Ads-SDK (~> 12.0) - GoogleUserMessagingPlatform (3.0.0) - local_auth_darwin (0.0.1): - Flutter @@ -101,6 +108,7 @@ DEPENDENCIES: - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - flutter_tts (from `.symlinks/plugins/flutter_tts/ios`) - geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`) + - gma_mediation_meta (from `.symlinks/plugins/gma_mediation_meta/ios`) - google_mobile_ads (from `.symlinks/plugins/google_mobile_ads/ios`) - local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`) - mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`) @@ -119,7 +127,9 @@ SPEC REPOS: trunk: - DKImagePickerController - DKPhotoGallery + - FBAudienceNetwork - Google-Mobile-Ads-SDK + - GoogleMobileAdsMediationFacebook - GoogleUserMessagingPlatform - SDWebImage - SwiftyGif @@ -143,6 +153,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_tts/ios" geolocator_apple: :path: ".symlinks/plugins/geolocator_apple/darwin" + gma_mediation_meta: + :path: ".symlinks/plugins/gma_mediation_meta/ios" google_mobile_ads: :path: ".symlinks/plugins/google_mobile_ads/ios" local_auth_darwin: @@ -175,6 +187,7 @@ SPEC CHECKSUMS: device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 + FBAudienceNetwork: 08e86d63a05b3a5a59414af12e4af8d756943c80 file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6 fl_downloader: dc99aa8dd303f862cccb830087f37acc9b0156ee @@ -182,8 +195,10 @@ SPEC CHECKSUMS: flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf flutter_tts: b88dbc8655d3dc961bc4a796e4e16a4cc1795833 geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e + gma_mediation_meta: 44defcf3b61414cdca65c0f897360e31b9332a09 Google-Mobile-Ads-SDK: 1dfb0c3cb46c7e2b00b0f4de74a1e06d9ea25d67 google_mobile_ads: 535223588a6791b7a3cc3513a1bc7b89d12f3e62 + GoogleMobileAdsMediationFacebook: b11a92ae3bfdae19853b882252b7e62791c18162 GoogleUserMessagingPlatform: f8d0cdad3ca835406755d0a69aa634f00e76d576 local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391 mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93 diff --git a/Frontend/ios/Runner/Info.plist b/Frontend/ios/Runner/Info.plist index 66f13c22..410a60ed 100644 --- a/Frontend/ios/Runner/Info.plist +++ b/Frontend/ios/Runner/Info.plist @@ -2,6 +2,17 @@ + SKAdNetworkItems + + + SKAdNetworkIdentifier + v9wttpbfk9.skadnetwork + + + SKAdNetworkIdentifier + n38lu8286q.skadnetwork + + GADApplicationIdentifier ca-app-pub-4781880856775334~6935644635 CADisableMinimumFrameDurationOnPhone diff --git a/Frontend/lib/main.dart b/Frontend/lib/main.dart index 4bdbd191..783a11a3 100644 --- a/Frontend/lib/main.dart +++ b/Frontend/lib/main.dart @@ -1,6 +1,19 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/about_mih_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_authentication_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calculator_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_wallet_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:provider/provider.dart'; import 'package:upgrader/upgrader.dart'; import 'mih_config/mih_env.dart'; import 'mih_config/mih_theme.dart'; @@ -66,19 +79,66 @@ class _MzansiInnovationHubState extends State { double width = MediaQuery.sizeOf(context).width; theme.setScreenType(width); precacheImage(theme.loadingImage(), context); - return MaterialApp.router( - title: getTitle(), - themeMode: ThemeMode.dark, - theme: theme.getThemeData(), - darkTheme: theme.getThemeData(), - debugShowCheckedModeBanner: false, - routerConfig: widget.router, - builder: (context, child) { - return UpgradeAlert( - navigatorKey: widget.router.routerDelegate.navigatorKey, - child: child ?? const Text('Upgrade Alert'), - ); - }, + return MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (context) => MihAuthenticationProvider(), + ), + ChangeNotifierProvider( + create: (context) => MzansiProfileProvider(), + ), + ChangeNotifierProvider( + create: (context) => MzansiWalletProvider(), + ), + ChangeNotifierProvider( + create: (context) => MzansiAiProvider(), + ), + ChangeNotifierProvider( + create: (context) => MzansiDirectoryProvider(), + ), + ChangeNotifierProvider( + create: (context) => MihBannerAdProvider(), + ), + ChangeNotifierProvider( + create: (context) => MihCalculatorProvider(), + ), + ChangeNotifierProvider( + create: (context) => MihAccessControllsProvider(), + ), + ChangeNotifierProvider( + create: (context) => MihCalendarProvider(), + ), + ChangeNotifierProvider( + create: (context) => AboutMihProvider(), + ), + ChangeNotifierProvider( + create: (context) => MihMineSweeperProvider(), + ), + ChangeNotifierProvider( + create: (context) => PatientManagerProvider(), + ), + ], + child: MaterialApp.router( + title: getTitle(), + themeMode: ThemeMode.dark, + theme: theme.getThemeData(), + darkTheme: theme.getThemeData(), + debugShowCheckedModeBanner: false, + routerConfig: widget.router, + builder: (context, child) { + if (child == null) { + return const Scaffold( + body: Center( + child: CircularProgressIndicator(), + ), + ); + } + return UpgradeAlert( + navigatorKey: widget.router.routerDelegate.navigatorKey, + child: child, + ); + }, + ), ); } } diff --git a/Frontend/lib/main_dev.dart b/Frontend/lib/main_dev.dart index 81ca7e45..c0bd70f0 100644 --- a/Frontend/lib/main_dev.dart +++ b/Frontend/lib/main_dev.dart @@ -20,6 +20,12 @@ void main() async { apiBasePath: "/auth", ); if (!kIsWeb) { + const List testDeviceIds = ['733d4c68-9b54-453a-9622-2df407310f40']; + MobileAds.instance.updateRequestConfiguration( + RequestConfiguration( + testDeviceIds: testDeviceIds, + ), + ); MobileAds.instance.initialize(); } else { usePathUrlStrategy(); @@ -29,5 +35,7 @@ void main() async { }); final GoRouter appRouter = MihGoRouter().mihRouter; FlutterNativeSplash.remove(); - runApp(MzansiInnovationHub(router: appRouter,)); + runApp(MzansiInnovationHub( + router: appRouter, + )); } diff --git a/Frontend/lib/mih_components/mih_objects/minesweeper_player_score.dart b/Frontend/lib/mih_components/mih_objects/minesweeper_player_score.dart new file mode 100644 index 00000000..9a1dad89 --- /dev/null +++ b/Frontend/lib/mih_components/mih_objects/minesweeper_player_score.dart @@ -0,0 +1,42 @@ +class MinesweeperPlayerScore { + String app_id; + String username; + String proPicUrl; + String difficulty; + String game_time; + double game_score; + DateTime played_date; + + MinesweeperPlayerScore({ + required this.app_id, + required this.username, + required this.proPicUrl, + required this.difficulty, + required this.game_time, + required this.game_score, + required this.played_date, + }); + + factory MinesweeperPlayerScore.fromJson(Map json) { + return MinesweeperPlayerScore( + app_id: json['app_id'], + username: json['username'], + proPicUrl: json['proPicUrl'], + difficulty: json['difficulty'], + game_time: json['game_time'], + game_score: json['game_score'], + played_date: DateTime.parse(json['played_date']), + ); + } + + Map toJson() { + return { + 'app_id': app_id, + 'username': username, + 'proPicUrl': proPicUrl, + 'difficulty': difficulty, + 'game_time': game_score, + 'played_date': played_date.toIso8601String(), + }; + } +} diff --git a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart index 16d0bd2c..e72699bf 100644 --- a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart +++ b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart @@ -396,7 +396,6 @@ class _PackageToolOneState extends State { return widget.business != null ? MihBusinessProfilePreview( business: widget.business!, - myLocation: myLocation, ) : Text("NoBusiness Data"); } @@ -424,7 +423,7 @@ class _PackageToolOneState extends State { "rating", "mission_vision", ), - startUpSearch: '', + // startUpSearch: '', width: 300, ).redacted( context: context, diff --git a/Frontend/lib/mih_components/mih_package_components/assets/fonts/Mih_Icons.ttf b/Frontend/lib/mih_components/mih_package_components/assets/fonts/Mih_Icons.ttf index 71c04e15..a908997c 100644 Binary files a/Frontend/lib/mih_components/mih_package_components/assets/fonts/Mih_Icons.ttf and b/Frontend/lib/mih_components/mih_package_components/assets/fonts/Mih_Icons.ttf differ diff --git a/Frontend/lib/mih_components/mih_package_components/assets/fonts/style.css b/Frontend/lib/mih_components/mih_package_components/assets/fonts/style.css index 97fe7b5a..9b49c4fc 100644 --- a/Frontend/lib/mih_components/mih_package_components/assets/fonts/style.css +++ b/Frontend/lib/mih_components/mih_package_components/assets/fonts/style.css @@ -1,10 +1,10 @@ @font-face { - font-family: 'Mih_Icons'; - src: url('fonts/Mih_Icons.eot?blbuxz'); - src: url('fonts/Mih_Icons.eot?blbuxz#iefix') format('embedded-opentype'), - url('fonts/Mih_Icons.ttf?blbuxz') format('truetype'), - url('fonts/Mih_Icons.woff?blbuxz') format('woff'), - url('fonts/Mih_Icons.svg?blbuxz#Mih_Icons') format('svg'); + font-family: 'icomoon'; + src: url('fonts/icomoon.eot?8flwgj'); + src: url('fonts/icomoon.eot?8flwgj#iefix') format('embedded-opentype'), + url('fonts/icomoon.ttf?8flwgj') format('truetype'), + url('fonts/icomoon.woff?8flwgj') format('woff'), + url('fonts/icomoon.svg?8flwgj#icomoon') format('svg'); font-weight: normal; font-style: normal; font-display: block; @@ -13,7 +13,7 @@ [class^="icon-"], [class*=" icon-"] { /* use !important to prevent issues with browser extensions that change fonts */ - font-family: 'Mih_Icons' !important; + font-family: 'icomoon' !important; /* speak: never; */ font-style: normal; font-weight: normal; @@ -26,70 +26,74 @@ -moz-osx-font-smoothing: grayscale; } -.icon-mzansi_directory:before { +.icon-mine_sweeper:before { content: "\e900"; } -.icon-personal_profile:before { +.icon-mzansi_directory:before { content: "\e901"; } -.icon-about_mih:before { +.icon-personal_profile:before { content: "\e902"; } -.icon-access_control:before { +.icon-about_mih:before { content: "\e903"; } -.icon-business_profile:before { +.icon-access_control:before { content: "\e904"; } -.icon-business_setup:before { +.icon-business_profile:before { content: "\e905"; } -.icon-i_dont_know:before { +.icon-business_setup:before { content: "\e906"; } -.icon-mih_logo:before { +.icon-calculator:before { content: "\e907"; } -.icon-mih_ring:before { +.icon-calendar:before { content: "\e908"; } -.icon-mzansi_ai:before { +.icon-i_dont_know:before { content: "\e909"; } -.icon-mzansi_wallet:before { +.icon-mih_logo:before { content: "\e90a"; } -.icon-notifications:before { +.icon-mih_ring:before { content: "\e90b"; } -.icon-patient_manager:before { +.icon-mzansi_ai:before { content: "\e90c"; } -.icon-patient_profile:before { +.icon-mzansi_wallet:before { content: "\e90d"; } -.icon-profile_setup:before { +.icon-notifications:before { content: "\e90e"; } -.icon-calculator:before { - content: "\e940"; +.icon-patient_manager:before { + content: "\e90f"; } -.icon-calendar:before { - content: "\e953"; +.icon-patient_profile:before { + content: "\e910"; +} + +.icon-profile_setup:before { + content: "\e911"; } \ No newline at end of file diff --git a/Frontend/lib/mih_components/mih_package_components/assets/images/loyalty_cards/mini/engen-min.png b/Frontend/lib/mih_components/mih_package_components/assets/images/loyalty_cards/mini/engen-min.png new file mode 100644 index 00000000..fb37347c Binary files /dev/null and b/Frontend/lib/mih_components/mih_package_components/assets/images/loyalty_cards/mini/engen-min.png differ diff --git a/Frontend/lib/mih_components/mih_package_components/mih_banner_ad.dart b/Frontend/lib/mih_components/mih_package_components/mih_banner_ad.dart index 521b3f88..8c52c32c 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_banner_ad.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_banner_ad.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:google_mobile_ads/google_mobile_ads.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:provider/provider.dart'; class MihBannerAd extends StatefulWidget { const MihBannerAd({super.key}); @@ -10,66 +12,26 @@ class MihBannerAd extends StatefulWidget { } class _MihBannerAdState extends State { - BannerAd? _bannerAd; - bool _isBannerAdLoaded = false; - final adUnitId = AppEnviroment.bannerAdUnitId; - String errorMessage = ''; - - void _loadBannerAd() { - _bannerAd = BannerAd( - adUnitId: adUnitId, - request: const AdRequest(), - size: AdSize.banner, - listener: BannerAdListener( - onAdLoaded: (ad) { - debugPrint('$ad loaded.'); - setState(() { - _isBannerAdLoaded = true; - }); - }, - onAdFailedToLoad: (ad, err) { - debugPrint('BannerAd failed to load: $err'); - setState(() { - errorMessage = - 'Failed to load ad- Message: ${err.message} Code :${err.code}'; - }); - ad.dispose(); // Dispose the ad to free resources - }, - onAdOpened: (Ad ad) => debugPrint('$ad opened.'), - onAdClosed: (Ad ad) => debugPrint('$ad closed.'), - onAdImpression: (Ad ad) => debugPrint('$ad impression.'), - ), - ); - - _bannerAd!.load(); - } - - @override - void dispose() { - _bannerAd?.dispose(); // Dispose the ad when the widget is removed - super.dispose(); - } - - @override - void initState() { - super.initState(); - _loadBannerAd(); - } - @override Widget build(BuildContext context) { - return Column( - children: [ - _bannerAd != null && _isBannerAdLoaded - ? SizedBox( - width: _bannerAd!.size.width.toDouble(), - height: _bannerAd!.size.height.toDouble(), - child: AdWidget(ad: _bannerAd!)) - : SizedBox( - child: - Text(AppEnviroment.getEnv() == "Dev" ? errorMessage : ""), - ), - ], + return Consumer( + builder: (context, bannerAdProvider, child) { + return Column( + children: [ + bannerAdProvider.bannerAd != null && + bannerAdProvider.isBannerAdLoaded + ? SizedBox( + width: bannerAdProvider.bannerAd!.size.width.toDouble(), + height: bannerAdProvider.bannerAd!.size.height.toDouble(), + child: AdWidget(ad: bannerAdProvider.bannerAd!)) + : SizedBox( + child: Text(AppEnviroment.getEnv() == "Dev" + ? bannerAdProvider.errorMessage + : ""), + ), + ], + ); + }, ); } } diff --git a/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart b/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart index 725c1183..53683653 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart @@ -4,17 +4,17 @@ import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; +import 'package:provider/provider.dart'; class MihBusinessProfilePreview extends StatefulWidget { final Business business; - final String? myLocation; const MihBusinessProfilePreview({ super.key, required this.business, - required this.myLocation, }); @override @@ -26,10 +26,10 @@ class _MihBusinessProfilePreviewState extends State { late Future futureImageUrl; PlatformFile? file; - String calculateDistance() { + String calculateDistance(MzansiDirectoryProvider directoryProvider) { try { double distanceInKm = MIHLocationAPI().getDistanceInMeaters( - widget.myLocation!, widget.business.gps_location) / + directoryProvider.userLocation, widget.business.gps_location) / 1000; return "${distanceInKm.toStringAsFixed(2)} km"; } catch (error) { @@ -48,73 +48,82 @@ class _MihBusinessProfilePreviewState extends State { @override Widget build(BuildContext context) { double profilePictureWidth = 60; - return Row( - children: [ - FutureBuilder( - future: futureImageUrl, - builder: (context, asyncSnapshot) { - if (asyncSnapshot.connectionState == ConnectionState.done && - asyncSnapshot.hasData) { - if (asyncSnapshot.requireData != "") { - return MihCircleAvatar( - imageFile: NetworkImage(asyncSnapshot.requireData), - width: profilePictureWidth, - editable: false, - fileNameController: TextEditingController(), - userSelectedfile: file, - frameColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - backgroundColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onChange: () {}, - ); - } else { - return Icon( - MihIcons.iDontKnow, - size: profilePictureWidth, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - } - } else { - return Icon( - MihIcons.mihRing, - size: profilePictureWidth, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - } - }), - const SizedBox(width: 15), - Column( - crossAxisAlignment: CrossAxisAlignment.start, + return Consumer( + builder: (BuildContext context, MzansiDirectoryProvider directoryProvider, + Widget? child) { + return Row( children: [ - Text( - widget.business.Name, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 18, - ), - ), - Text( - widget.business.type, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 15, - ), - ), - Text( - widget.myLocation != null || widget.myLocation!.isEmpty - ? calculateDistance() - : "0.00 km", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 10, - ), - ), + FutureBuilder( + future: futureImageUrl, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == ConnectionState.done && + asyncSnapshot.hasData) { + if (asyncSnapshot.requireData != "") { + return MihCircleAvatar( + imageFile: NetworkImage(asyncSnapshot.requireData), + width: profilePictureWidth, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.iDontKnow, + size: profilePictureWidth, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ); + } + } else { + return Icon( + MihIcons.mihRing, + size: profilePictureWidth, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ); + } + }), + const SizedBox(width: 15), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.business.Name, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + Text( + widget.business.type, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 15, + ), + ), + Text( + directoryProvider.userPosition != null + ? calculateDistance(directoryProvider) + : "0.00 km", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 10, + ), + ), + ], + ) ], - ) - ], + ); + }, ); } } diff --git a/Frontend/lib/mih_components/mih_package_components/mih_button.dart b/Frontend/lib/mih_components/mih_package_components/mih_button.dart index 4166f475..6e76d55c 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_button.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_button.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; class MihButton extends StatelessWidget { final void Function()? onPressed; + final void Function()? onLongPressed; final Color buttonColor; final double? width; final double? height; @@ -12,6 +13,7 @@ class MihButton extends StatelessWidget { const MihButton({ super.key, required this.onPressed, + this.onLongPressed, required this.buttonColor, this.width, this.height, @@ -49,6 +51,7 @@ class MihButton extends StatelessWidget { highlightColor: rippleColor.withValues(alpha: 0.2), hoverColor: rippleColor.withValues(alpha: 0.3), onTap: onPressed, + onLongPress: onLongPressed, child: Container( width: width, height: height, diff --git a/Frontend/lib/mih_components/mih_package_components/mih_calendar.dart b/Frontend/lib/mih_components/mih_package_components/mih_calendar.dart index 01fc2f18..8989da51 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_calendar.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_calendar.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:provider/provider.dart'; import 'package:table_calendar/table_calendar.dart'; class MIHCalendar extends StatefulWidget { @@ -19,16 +22,29 @@ class MIHCalendar extends StatefulWidget { } class _MIHCalendarState extends State { - DateTime selectedDay = DateTime.now(); + late DateTime selectedDay; CalendarFormat _calendarFormat = CalendarFormat.week; void onDaySelected(DateTime day, DateTime focusedDay) { + KenLogger.success("Selected Day: $day"); setState(() { selectedDay = day; }); widget.setDate(selectedDay.toString().split(" ")[0]); } + @override + void initState() { + super.initState(); + MihCalendarProvider mihCalendarProvider = + context.read(); + if (mihCalendarProvider.selectedDay.isNotEmpty) { + selectedDay = DateTime.parse(mihCalendarProvider.selectedDay); + } else { + selectedDay = DateTime.now(); + } + } + @override Widget build(BuildContext context) { return SizedBox( diff --git a/Frontend/lib/mih_components/mih_package_components/mih_circle_avatar.dart b/Frontend/lib/mih_components/mih_package_components/mih_circle_avatar.dart index 4f0c3e71..c64aaa75 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_circle_avatar.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_circle_avatar.dart @@ -10,7 +10,7 @@ class MihCircleAvatar extends StatefulWidget { final ImageProvider? imageFile; final double width; final bool editable; - final TextEditingController fileNameController; + final TextEditingController? fileNameController; final onChange; final PlatformFile? userSelectedfile; final Color frameColor; @@ -130,7 +130,7 @@ class _MihCircleAvatarState extends State { }); setState(() { - widget.fileNameController.text = selectedFile.name; + widget.fileNameController!.text = selectedFile.name; }); } else { if (result != null) { @@ -148,7 +148,7 @@ class _MihCircleAvatarState extends State { }); setState(() { - widget.fileNameController.text = + widget.fileNameController!.text = file.path.split('/').last; }); } else { @@ -157,7 +157,7 @@ class _MihCircleAvatarState extends State { } } } catch (e) { - print("Error: $e"); + print("Here Error: $e"); } }, icon: Icon( diff --git a/Frontend/lib/mih_components/mih_package_components/mih_dropdwn_field.dart b/Frontend/lib/mih_components/mih_package_components/mih_dropdwn_field.dart index 9bd6d44f..9c0d6154 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_dropdwn_field.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_dropdwn_field.dart @@ -10,6 +10,7 @@ class MihDropdownField extends StatefulWidget { final bool editable; final bool enableSearch; final FormFieldValidator? validator; + final Function(String?)? onSelected; const MihDropdownField({ super.key, @@ -20,6 +21,7 @@ class MihDropdownField extends StatefulWidget { required this.editable, required this.enableSearch, this.validator, + this.onSelected, }); @override @@ -117,8 +119,10 @@ class _MihDropdownFieldState extends State { enableSearch: widget.enableSearch, enableFilter: widget.enableSearch, enabled: widget.editable, - textInputAction: TextInputAction.search, - requestFocusOnTap: true, + textInputAction: widget.enableSearch + ? TextInputAction.search + : TextInputAction.none, + requestFocusOnTap: widget.enableSearch, menuHeight: 400, expandedInsets: EdgeInsets.zero, textStyle: TextStyle( @@ -153,6 +157,7 @@ class _MihDropdownFieldState extends State { ), onSelected: (String? selectedValue) { field.didChange(selectedValue); + widget.onSelected?.call(selectedValue); }, menuStyle: MenuStyle( backgroundColor: WidgetStatePropertyAll( diff --git a/Frontend/lib/mih_components/mih_package_components/mih_icons.dart b/Frontend/lib/mih_components/mih_package_components/mih_icons.dart index bfd4a9ac..6dbb19c8 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_icons.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_icons.dart @@ -11,54 +11,57 @@ class MihIcons { // IconData constants based on your style.css file // Note: We convert the hex code from CSS (\eXXX) to an integer (0xeXXX) - static const IconData mzansiDirectory = + static const IconData mineSweeper = IconData(0xe900, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData personalProfile = + static const IconData mzansiDirectory = IconData(0xe901, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData aboutMih = + static const IconData personalProfile = IconData(0xe902, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData accessControl = + static const IconData aboutMih = IconData(0xe903, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData businessProfile = + static const IconData accessControl = IconData(0xe904, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData businessSetup = + static const IconData businessProfile = IconData(0xe905, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData iDontKnow = + static const IconData businessSetup = IconData(0xe906, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData mihLogo = + static const IconData calculator = IconData(0xe907, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData mihRing = + static const IconData calendar = IconData(0xe908, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData mzansiAi = + static const IconData iDontKnow = IconData(0xe909, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData mzansiWallet = + static const IconData mihLogo = IconData(0xe90a, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData notifications = + static const IconData mihRing = IconData(0xe90b, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData patientManager = + static const IconData mzansiAi = IconData(0xe90c, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData patientProfile = + static const IconData mzansiWallet = IconData(0xe90d, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData profileSetup = + static const IconData notifications = IconData(0xe90e, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData calculator = - IconData(0xe940, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); + static const IconData patientManager = + IconData(0xe90f, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); - static const IconData calendar = - IconData(0xe953, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); + static const IconData patientProfile = + IconData(0xe910, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); + + static const IconData profileSetup = + IconData(0xe911, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); } diff --git a/Frontend/lib/mih_components/mih_package_components/mih_image_display.dart b/Frontend/lib/mih_components/mih_package_components/mih_image_display.dart index c33fe4f7..509fcc59 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_image_display.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_image_display.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; @@ -32,19 +33,9 @@ class _MihImageDisplayState extends State { late ImageProvider? imagePreview; ImageProvider? getImage() { - Color dark = const Color(0XFF3A4454); + KenLogger.success(widget.imageFile.toString()); if (widget.imageFile == null) { - if (MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark") == - dark) { - print("here in light icon"); - return const AssetImage( - 'lib/mih_components/mih_package_components/assets/images/i-dont-know-dark.png'); - } else { - print("here in dark icon"); - return const AssetImage( - 'lib/mih_components/mih_package_components/assets/images/i-dont-know-light.png'); - } + return null; } else { return widget.imageFile; } @@ -69,10 +60,26 @@ class _MihImageDisplayState extends State { child: Stack( alignment: Alignment.center, children: [ - ClipRRect( - borderRadius: BorderRadius.circular(widget.width * 0.1), - child: Image(image: imagePreview!), - ), + imagePreview != null + ? ClipRRect( + borderRadius: BorderRadius.circular(widget.width * 0.1), + child: Image(image: imagePreview!), + ) + : Container( + width: widget.width, + height: widget.height, + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + borderRadius: BorderRadius.circular(widget.width * 0.1), + ), + child: Icon( + Icons.image_not_supported_rounded, + size: widget.width * 0.3, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), Visibility( visible: widget.editable, child: Positioned( @@ -133,7 +140,7 @@ class _MihImageDisplayState extends State { } } } catch (e) { - print("Error: $e"); + print("here 2 Error: $e"); } }, icon: const Icon( diff --git a/Frontend/lib/mih_components/mih_package_components/mih_package_alert.dart b/Frontend/lib/mih_components/mih_package_components/mih_package_alert.dart index ce87d21f..a087be0c 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_package_alert.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_package_alert.dart @@ -35,7 +35,7 @@ class _MihPackageAlertState extends State { setState(() { popUpWidth = (size!.width / 4) * 2; popUpheight = null; - popUpTitleSize = 25.0; + popUpTitleSize = 30.0; popUpSubtitleSize = 20.0; popUpBodySize = 15; popUpPaddingSize = 25.0; @@ -45,7 +45,7 @@ class _MihPackageAlertState extends State { setState(() { popUpWidth = size!.width - (size!.width * 0.1); popUpheight = null; - popUpTitleSize = 20.0; + popUpTitleSize = 25.0; popUpSubtitleSize = 18.0; popUpBodySize = 15; popUpPaddingSize = 15.0; diff --git a/Frontend/lib/mih_components/mih_package_components/mih_text_form_field.dart b/Frontend/lib/mih_components/mih_package_components/mih_text_form_field.dart index 03d44871..176d26bb 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_text_form_field.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_text_form_field.dart @@ -191,18 +191,21 @@ class _MihTextFormFieldState extends State { ), decoration: InputDecoration( suffixIcon: widget.passwordMode == true - ? IconButton( - icon: Icon( - _obscureText - ? Icons.visibility_off - : Icons.visibility, - color: widget.inputColor, + ? FocusScope( + canRequestFocus: false, + child: IconButton( + icon: Icon( + _obscureText + ? Icons.visibility_off + : Icons.visibility, + color: widget.inputColor, + ), + onPressed: () { + setState(() { + _obscureText = !_obscureText; + }); + }, ), - onPressed: () { - setState(() { - _obscureText = !_obscureText; - }); - }, ) : null, errorStyle: const TextStyle( diff --git a/Frontend/lib/mih_components/mih_providers/about_mih_provider.dart b/Frontend/lib/mih_components/mih_providers/about_mih_provider.dart new file mode 100644 index 00000000..18b2e985 --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/about_mih_provider.dart @@ -0,0 +1,19 @@ +import 'package:flutter/foundation.dart'; + +class AboutMihProvider extends ChangeNotifier { + int toolIndex; + + AboutMihProvider({ + this.toolIndex = 0, + }); + + void reset() { + toolIndex = 0; + notifyListeners(); + } + + void setToolIndex(int index) { + toolIndex = index; + notifyListeners(); + } +} diff --git a/Frontend/lib/mih_components/mih_providers/mih_access_controlls_provider.dart b/Frontend/lib/mih_components/mih_providers/mih_access_controlls_provider.dart new file mode 100644 index 00000000..dd7f11a0 --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/mih_access_controlls_provider.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart'; + +class MihAccessControllsProvider extends ChangeNotifier { + int toolIndex; + List? accessList; + + MihAccessControllsProvider({ + this.toolIndex = 0, + }); + + void reset() { + toolIndex = 0; + accessList = null; + notifyListeners(); + } + + void setToolIndex(int index) { + toolIndex = index; + } + + void setAccessList(List accesses) { + accessList = accesses; + notifyListeners(); + } + + void editAccessItem(PatientAccess updatedAccess) { + if (accessList == null) return; + int index = accessList!.indexWhere((access) => + access.app_id == updatedAccess.app_id && + access.business_id == updatedAccess.business_id); + if (index != -1) { + accessList![index] = updatedAccess; + notifyListeners(); + } + } +} diff --git a/Frontend/lib/mih_components/mih_providers/mih_authentication_provider.dart b/Frontend/lib/mih_components/mih_providers/mih_authentication_provider.dart new file mode 100644 index 00000000..d53213bc --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/mih_authentication_provider.dart @@ -0,0 +1,19 @@ +import 'package:flutter/foundation.dart'; + +class MihAuthenticationProvider extends ChangeNotifier { + int toolIndex; + + MihAuthenticationProvider({ + this.toolIndex = 0, + }); + + void reset() { + toolIndex = 0; + notifyListeners(); + } + + void setToolIndex(int index) { + toolIndex = index; + notifyListeners(); + } +} diff --git a/Frontend/lib/mih_components/mih_providers/mih_banner_ad_provider.dart b/Frontend/lib/mih_components/mih_providers/mih_banner_ad_provider.dart new file mode 100644 index 00000000..560fc91a --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/mih_banner_ad_provider.dart @@ -0,0 +1,57 @@ +import 'package:flutter/foundation.dart'; +import 'package:google_mobile_ads/google_mobile_ads.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; + +class MihBannerAdProvider extends ChangeNotifier { + BannerAd? bannerAd; + final adUnitId = AppEnviroment.bannerAdUnitId; + bool isBannerAdLoaded = false; + String errorMessage = ''; + + MihBannerAdProvider({ + this.bannerAd, + this.isBannerAdLoaded = false, + this.errorMessage = '', + }); + + void reset() { + bannerAd = null; + isBannerAdLoaded = false; + errorMessage = ""; + notifyListeners(); + } + + @override + void dispose() { + bannerAd?.dispose(); + super.dispose(); + } + + void loadBannerAd() { + bannerAd = BannerAd( + adUnitId: adUnitId, + request: const AdRequest(), + size: AdSize.banner, + listener: BannerAdListener( + onAdLoaded: (ad) { + debugPrint('$ad loaded.'); + isBannerAdLoaded = true; + notifyListeners(); + }, + onAdFailedToLoad: (ad, err) { + debugPrint('BannerAd failed to load: $err'); + errorMessage = + 'Failed to load ad- Message: ${err.message} Code :${err.code}'; + ad.dispose(); // Dispose the ad to free resources + isBannerAdLoaded = false; // ⬅️ Explicitly set to false + bannerAd = null; // ⬅️ Explicitly set to null + notifyListeners(); + }, + onAdOpened: (Ad ad) => debugPrint('$ad opened.'), + onAdClosed: (Ad ad) => debugPrint('$ad closed.'), + onAdImpression: (Ad ad) => debugPrint('$ad impression.'), + ), + ); + bannerAd!.load(); + } +} diff --git a/Frontend/lib/mih_components/mih_providers/mih_calculator_provider.dart b/Frontend/lib/mih_components/mih_providers/mih_calculator_provider.dart new file mode 100644 index 00000000..29052ff7 --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/mih_calculator_provider.dart @@ -0,0 +1,27 @@ +import 'package:flutter/foundation.dart'; + +class MihCalculatorProvider extends ChangeNotifier { + List availableCurrencies; + int toolIndex; + + MihCalculatorProvider({ + this.availableCurrencies = const [], + this.toolIndex = 0, + }); + + void reset() { + availableCurrencies = []; + toolIndex = 0; + notifyListeners(); + } + + void setToolIndex(int index) { + toolIndex = index; + notifyListeners(); + } + + void setAvailableCurrencies({required List currencies}) async { + availableCurrencies = currencies; + notifyListeners(); + } +} diff --git a/Frontend/lib/mih_components/mih_providers/mih_calendar_provider.dart b/Frontend/lib/mih_components/mih_providers/mih_calendar_provider.dart new file mode 100644 index 00000000..40265f45 --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/mih_calendar_provider.dart @@ -0,0 +1,87 @@ +import 'package:flutter/foundation.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/appointment.dart'; + +class MihCalendarProvider extends ChangeNotifier { + int toolIndex; + String selectedDay = DateTime.now().toString().split(" ")[0]; + List? personalAppointments; + List? businessAppointments; + + MihCalendarProvider({ + this.toolIndex = 0, + }); + + void reset() { + toolIndex = 0; + personalAppointments = null; + businessAppointments = null; + notifyListeners(); + } + + void setToolIndex(int index) { + toolIndex = index; + notifyListeners(); + } + + void setSelectedDay(String day) { + selectedDay = day; + notifyListeners(); + } + + void resetSelectedDay() { + selectedDay = DateTime.now().toString().split(" ")[0]; + notifyListeners(); + } + + void setPersonalAppointments({required List appointments}) { + personalAppointments = appointments; + notifyListeners(); + } + + void setBusinessAppointments({required List appointments}) { + businessAppointments = appointments; + notifyListeners(); + } + + void addPersonalAppointment({required Appointment newAppointment}) { + personalAppointments?.add(newAppointment); + notifyListeners(); + } + + void addBusinessAppointment({required Appointment newAppointment}) { + businessAppointments?.add(newAppointment); + notifyListeners(); + } + + void editPersonalAppointment({required Appointment updatedAppointment}) { + int index = personalAppointments?.indexWhere((appointment) => + appointment.idappointments == updatedAppointment.idappointments) ?? + -1; + if (index != -1) { + personalAppointments?[index] = updatedAppointment; + notifyListeners(); + } + } + + void editBusinessAppointment({required Appointment updatedAppointment}) { + int index = businessAppointments?.indexWhere((appointment) => + appointment.idappointments == updatedAppointment.idappointments) ?? + -1; + if (index != -1) { + businessAppointments?[index] = updatedAppointment; + notifyListeners(); + } + } + + void deletePersonalAppointment({required int appointmentId}) { + personalAppointments?.removeWhere( + (appointment) => appointment.idappointments == appointmentId); + notifyListeners(); + } + + void deleteBusinessAppointment({required int appointmentId}) { + businessAppointments?.removeWhere( + (appointment) => appointment.idappointments == appointmentId); + notifyListeners(); + } +} diff --git a/Frontend/lib/mih_components/mih_providers/mih_mine_sweeper_provider.dart b/Frontend/lib/mih_components/mih_providers/mih_mine_sweeper_provider.dart new file mode 100644 index 00000000..50b58831 --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/mih_mine_sweeper_provider.dart @@ -0,0 +1,81 @@ +import 'package:flutter/widgets.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/minesweeper_player_score.dart'; + +class MihMineSweeperProvider extends ChangeNotifier { + String difficulty; + int toolIndex; + int rowCount; + int columnCount; + int totalMines; + List? leaderboard; + List? myScoreboard; + List?> leaderboardUserPictures = []; + + MihMineSweeperProvider({ + this.difficulty = "Easy", + this.toolIndex = 0, + this.rowCount = 10, + this.columnCount = 10, + this.totalMines = 15, + }); + + void reset() { + difficulty = "Easy"; + toolIndex = 0; + rowCount = 10; + columnCount = 10; + totalMines = 15; + notifyListeners(); + } + + void setDifficulty(String difficulty) { + this.difficulty = difficulty; + notifyListeners(); + } + + void setToolIndex(int index) { + toolIndex = index; + notifyListeners(); + } + + void setRowCount(int rowCount) { + this.rowCount = rowCount; + notifyListeners(); + } + + void setCoulmnCount(int columnCount) { + this.columnCount = columnCount; + notifyListeners(); + } + + void setTotalMines(int totalMines) { + this.totalMines = totalMines; + notifyListeners(); + } + + void setLeaderboard({required List? leaderboard}) { + if (leaderboard == null) { + this.leaderboard = []; + } else { + this.leaderboard = leaderboard; + } + notifyListeners(); + } + + void setMyScoreboard({ + required List? myScoreboard, + }) { + if (myScoreboard == null) { + this.myScoreboard = []; + } else { + this.myScoreboard = myScoreboard; + } + notifyListeners(); + } + + void setLeaderboardUserPictures( + {required List?> leaderboardUserPictures}) { + this.leaderboardUserPictures = leaderboardUserPictures; + notifyListeners(); + } +} diff --git a/Frontend/lib/mih_components/mih_providers/mzansi_ai_provider.dart b/Frontend/lib/mih_components/mih_providers/mzansi_ai_provider.dart new file mode 100644 index 00000000..1ba96af5 --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/mzansi_ai_provider.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +class MzansiAiProvider extends ChangeNotifier { + int toolIndex; + String? startUpQuestion; + + MzansiAiProvider({ + this.toolIndex = 0, + }); + + void reset() { + toolIndex = 0; + startUpQuestion = null; + notifyListeners(); + } + + void setToolIndex(int index) { + toolIndex = index; + notifyListeners(); + } + + void setStartUpQuestion(String? question) { + startUpQuestion = question; + notifyListeners(); + } +} diff --git a/Frontend/lib/mih_components/mih_providers/mzansi_directory_provider.dart b/Frontend/lib/mih_components/mih_providers/mzansi_directory_provider.dart new file mode 100644 index 00000000..59f148bc --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/mzansi_directory_provider.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; + +class MzansiDirectoryProvider extends ChangeNotifier { + int toolIndex; + Position? userPosition; + String userLocation; + bool personalSearch; + List bookmarkedBusinesses = []; + Map businessDetailsMap = {}; + List? searchedBusinesses; + Business? selectedBusiness; + List? searchedUsers; + AppUser? selectedUser; + String searchTerm; + String businessTypeFilter; + + MzansiDirectoryProvider({ + this.toolIndex = 0, + this.personalSearch = true, + this.userLocation = "Unknown Location", + this.searchTerm = "", + this.businessTypeFilter = "", + }); + + void reset() { + toolIndex = 0; + userPosition = null; + userLocation = "Unknown Location"; + personalSearch = true; + bookmarkedBusinesses = []; + businessDetailsMap = {}; + searchedBusinesses = null; + selectedBusiness = null; + searchedUsers = null; + selectedUser = null; + searchTerm = ""; + businessTypeFilter = ""; + notifyListeners(); + } + + void setToolIndex(int index) { + toolIndex = index; + notifyListeners(); + } + + void setUserPosition(Position? position) { + userPosition = position; + if (position == null) { + userLocation = "Unknown Location"; + } else { + userLocation = "${position.latitude}, ${position.longitude}"; + } + notifyListeners(); + } + + void setPersonalSearch(bool personal) { + personalSearch = personal; + notifyListeners(); + } + + void setFavouriteBusinesses({required List businesses}) { + bookmarkedBusinesses = businesses; + notifyListeners(); + } + + void setBusinessDetailsMap({required Map detailsMap}) { + businessDetailsMap = detailsMap; + notifyListeners(); + } + + void setSearchedBusinesses({required List searchedBusinesses}) { + this.searchedBusinesses = searchedBusinesses; + notifyListeners(); + } + + void setSelectedBusiness({required Business business}) { + selectedBusiness = business; + notifyListeners(); + } + + void setSearchedUsers({required List searchedUsers}) { + this.searchedUsers = searchedUsers; + notifyListeners(); + } + + void setSelectedUser({required AppUser user}) { + selectedUser = user; + notifyListeners(); + } + + void setSearchTerm({required String searchTerm}) { + this.searchTerm = searchTerm; + notifyListeners(); + } + + void setBusinessTypeFilter({required String businessTypeFilter}) { + this.businessTypeFilter = businessTypeFilter; + notifyListeners(); + } +} diff --git a/Frontend/lib/mih_components/mih_providers/mzansi_profile_provider.dart b/Frontend/lib/mih_components/mih_providers/mzansi_profile_provider.dart new file mode 100644 index 00000000..3570dc3c --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/mzansi_profile_provider.dart @@ -0,0 +1,141 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/user_consent.dart'; + +class MzansiProfileProvider extends ChangeNotifier { + bool personalHome; + int personalIndex; + int businessIndex; + AppUser? user; + String? userProfilePicUrl; + ImageProvider? userProfilePicture; + Business? business; + String? businessProfilePicUrl; + ImageProvider? businessProfilePicture; + BusinessUser? businessUser; + String? businessUserSignatureUrl; + ImageProvider? businessUserSignature; + UserConsent? userConsent; + List? employeeList; + List userSearchResults = []; + + MzansiProfileProvider({ + this.personalHome = true, + this.personalIndex = 0, + this.businessIndex = 0, + }); + + void reset() { + personalHome = true; + personalIndex = 0; + businessIndex = 0; + user = null; + userProfilePicUrl = null; + userProfilePicture = null; + business = null; + businessProfilePicUrl = null; + businessProfilePicture = null; + businessUser = null; + businessUserSignatureUrl = null; + businessUserSignature = null; + userConsent = null; + notifyListeners(); + } + + void setPersonalHome(bool isPersonalHome) { + personalHome = isPersonalHome; + notifyListeners(); + } + + void setPersonalIndex(int index) { + personalIndex = index; + notifyListeners(); + } + + void setBusinessIndex(int index) { + businessIndex = index; + notifyListeners(); + } + + void setUser({ + required AppUser newUser, + }) { + user = newUser; + notifyListeners(); + } + + void setUserProfilePicUrl(String url) { + userProfilePicUrl = url; + userProfilePicture = url.isNotEmpty ? NetworkImage(url) : null; + notifyListeners(); + } + + void setBusiness({ + Business? newBusiness, + }) { + business = newBusiness; + notifyListeners(); + } + + void setBusinessProfilePicUrl(String url) { + businessProfilePicUrl = url; + businessProfilePicture = url.isNotEmpty ? NetworkImage(url) : null; + notifyListeners(); + } + + void setBusinessUser({required BusinessUser newBusinessUser}) { + businessUser = newBusinessUser; + notifyListeners(); + } + + void setBusinessUserSignatureUrl(String url) { + businessUserSignatureUrl = url; + businessUserSignature = url.isNotEmpty ? NetworkImage(url) : null; + notifyListeners(); + } + + void setUserConsent(UserConsent? newUserConsent) { + userConsent = newUserConsent; + notifyListeners(); + } + + void setEmployeeList({required List employeeList}) { + this.employeeList = employeeList; + notifyListeners(); + } + + void addLoyaltyCard({required BusinessEmployee newEmployee}) { + employeeList!.add(newEmployee); + notifyListeners(); + } + + void updateEmplyeeDetails({required BusinessEmployee updatedEmployee}) { + int index = employeeList!.indexWhere((employee) => + employee.business_id == updatedEmployee.business_id && + employee.app_id == updatedEmployee.app_id); + if (index != -1) { + employeeList![index] = updatedEmployee; + notifyListeners(); + } + } + + void deleteEmplyee({required BusinessEmployee deletedEmployee}) { + employeeList!.removeWhere((employee) => + employee.business_id == deletedEmployee.business_id && + employee.app_id == deletedEmployee.app_id); + notifyListeners(); + } + + void addEmployee({required BusinessEmployee newEmployee}) { + employeeList!.add(newEmployee); + notifyListeners(); + } + + void setUserearchResults({required List userSearchResults}) { + this.userSearchResults = userSearchResults; + notifyListeners(); + } +} diff --git a/Frontend/lib/mih_components/mih_providers/mzansi_wallet_provider.dart b/Frontend/lib/mih_components/mih_providers/mzansi_wallet_provider.dart new file mode 100644 index 00000000..f09a3135 --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/mzansi_wallet_provider.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/loyalty_card.dart'; + +class MzansiWalletProvider extends ChangeNotifier { + List loyaltyCards; + List favouriteCards; + int toolIndex; + + MzansiWalletProvider({ + this.loyaltyCards = const [], + this.favouriteCards = const [], + this.toolIndex = 0, + }); + + void reset() { + toolIndex = 0; + loyaltyCards = []; + favouriteCards = []; + } + + void setToolIndex(int index) { + toolIndex = index; + notifyListeners(); + } + + void setLoyaltyCards({required List cards}) async { + loyaltyCards = cards; + notifyListeners(); + } + + void setFavouriteCards({required List cards}) async { + favouriteCards = cards; + notifyListeners(); + } + + void addLoyaltyCard({required MIHLoyaltyCard newCard}) { + loyaltyCards.add(newCard); + notifyListeners(); + } + + void deleteLoyaltyCard({required int cardId}) { + loyaltyCards.removeWhere((card) => card.idloyalty_cards == cardId); + notifyListeners(); + } + + void editLoyaltyCard({required MIHLoyaltyCard updatedCard}) { + int index = loyaltyCards.indexWhere( + (card) => card.idloyalty_cards == updatedCard.idloyalty_cards); + if (index != -1) { + loyaltyCards[index] = updatedCard; + notifyListeners(); + } + } +} diff --git a/Frontend/lib/mih_components/mih_providers/patient_manager_provider.dart b/Frontend/lib/mih_components/mih_providers/patient_manager_provider.dart new file mode 100644 index 00000000..03761c94 --- /dev/null +++ b/Frontend/lib/mih_components/mih_providers/patient_manager_provider.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/claim_statement_file.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/files.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/notes.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; + +class PatientManagerProvider extends ChangeNotifier { + int patientProfileIndex; + int patientManagerIndex; + int fileViewerIndex; + bool personalMode; + List? myPaitentList; + Patient? selectedPatient; + List? consultationNotes; + List? patientDocuments; + List? patientClaimsDocuments; + List patientSearchResults = []; + + PatientManagerProvider({ + this.patientProfileIndex = 0, + this.patientManagerIndex = 0, + this.fileViewerIndex = 0, + this.personalMode = true, + }); + + void reset() { + patientProfileIndex = 0; + patientManagerIndex = 0; + personalMode = true; + selectedPatient = null; + } + + void setPatientProfileIndex(int index) { + patientProfileIndex = index; + notifyListeners(); + } + + void setPatientManagerIndex(int index) { + patientManagerIndex = index; + notifyListeners(); + } + + void setFileViewerIndex(int index) { + patientProfileIndex = index; + notifyListeners(); + } + + void setPersonalMode(bool personalMode) { + this.personalMode = personalMode; + notifyListeners(); + } + + void setSelectedPatient({required Patient? selectedPatient}) { + this.selectedPatient = selectedPatient; + notifyListeners(); + } + + void setMyPatientList({required List? myPaitentList}) { + this.myPaitentList = myPaitentList ?? []; + notifyListeners(); + } + + void setConsultationNotes({required List? consultationNotes}) { + this.consultationNotes = consultationNotes ?? []; + notifyListeners(); + } + + void setPatientDocuments({required List? patientDocuments}) { + this.patientDocuments = patientDocuments ?? []; + notifyListeners(); + } + + void setClaimsDocuments( + {required List? patientClaimsDocuments}) { + this.patientClaimsDocuments = patientClaimsDocuments ?? []; + notifyListeners(); + } + + void setPatientSearchResults({required List patientSearchResults}) { + this.patientSearchResults = patientSearchResults; + notifyListeners(); + } +} diff --git a/Frontend/lib/mih_config/mih_colors.dart b/Frontend/lib/mih_config/mih_colors.dart index 6c69d0a9..724868e4 100644 --- a/Frontend/lib/mih_config/mih_colors.dart +++ b/Frontend/lib/mih_config/mih_colors.dart @@ -37,7 +37,7 @@ class MihColors { if (darkMode == true) { return const Color(0xff8ae290); } else { - return const Color(0xffB0F2B4); + return const Color(0xFF41B349); } } @@ -63,7 +63,7 @@ class MihColors { return const Color(0xffd69d7d); } else { // Add a different shade of pink for light mode - return const Color(0xffd69d7d); + return const Color(0xFFBD7145); } } @@ -81,7 +81,7 @@ class MihColors { return const Color(0xff6e7dcc); } else { // Add a different shade of pink for light mode - return const Color(0xff6e7dcc); + return const Color(0xFF5567C0); } } @@ -90,7 +90,34 @@ class MihColors { return const Color(0xffb682e7); } else { // Add a different shade of pink for light mode - return const Color(0xffb682e7); + return const Color(0xFF9857D4); + } + } + + static Color getGoldColor(bool darkMode) { + if (darkMode == true) { + return const Color(0xFFD4AF37); + } else { + // Add a different shade of pink for light mode + return const Color(0xffFFD700); + } + } + + static Color getSilverColor(bool darkMode) { + if (darkMode == true) { + return const Color(0xffC0C0C0); + } else { + // Add a different shade of pink for light mode + return const Color(0xFFA6A6A6); + } + } + + static Color getBronze(bool darkMode) { + if (darkMode == true) { + return const Color(0xffB1560F); + } else { + // Add a different shade of pink for light mode + return const Color(0xFFCD7F32); } } } diff --git a/Frontend/lib/mih_config/mih_go_router.dart b/Frontend/lib/mih_config/mih_go_router.dart index 7ac1e756..71de50cc 100644 --- a/Frontend/lib/mih_config/mih_go_router.dart +++ b/Frontend/lib/mih_config/mih_go_router.dart @@ -1,9 +1,10 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_print_prevew.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/Example/package_test.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_packages/about_mih/about_mih.dart'; import 'package:mzansi_innovation_hub/mih_packages/access_review/mih_access.dart'; import 'package:mzansi_innovation_hub/mih_packages/calculator/mih_calculator.dart'; @@ -13,21 +14,22 @@ import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/mih_auth_p import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/mih_authentication.dart'; import 'package:mzansi_innovation_hub/mih_packages/mih_home/mih_home.dart'; import 'package:mzansi_innovation_hub/mih_packages/mih_home/mih_route_error.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/mih_mine_sweeper.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/mzansi_ai.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/mzansi_directory.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart'; -import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/profile_business_add.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/mzansi_set_up_business_profile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart'; import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/components/mih_barcode_scanner.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/mih_wallet.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/pat_manager.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/add_or_view_patient.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/components/full_screen_file.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/patient_edit.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/patient_profile.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/pat_manager.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/components/full_screen_file.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/patient_profile.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/patient_set_up.dart'; +import 'package:provider/provider.dart'; import 'package:supertokens_flutter/supertokens.dart'; class MihGoRouterPaths { @@ -50,7 +52,6 @@ class MihGoRouterPaths { static const String businessProfileView = '/business-profile/view'; static const String patientProfile = '/patient-profile'; static const String patientProfileSetup = '/patient-profile/set-up'; - static const String patientProfileEdit = '/patient-profile/edit'; static const String mzansiWallet = '/mzansi-wallet'; static const String mzansiDirectory = '/mzansi-directory'; static const String mihAccess = '/mih-access'; @@ -63,6 +64,7 @@ class MihGoRouterPaths { static const String barcodeScanner = '/scanner'; static const String calculator = '/calculator'; static const String mzansiAi = '/mzansi-ai'; + static const String mihMineSweeper = '/mih-minesweeper'; static const String packageDevTest = '/package-dev'; } @@ -131,16 +133,8 @@ class MihGoRouter { path: MihGoRouterPaths.mihHome, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: mihHome"); - if (state.extra != null) { - final bool personalSelected = state.extra as bool; - return MihHome( - key: UniqueKey(), - personalSelected: personalSelected, - ); - } return MihHome( key: UniqueKey(), - personalSelected: true, ); }, ), @@ -150,14 +144,7 @@ class MihGoRouter { path: MihGoRouterPaths.aboutMih, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: aboutMih"); - final AboutArguments? args = state.extra as AboutArguments?; - int index = 0; - bool personalSelected = true; - if (args != null) { - index = args.packageIndex ?? 0; - personalSelected = args.personalSelected; - } - return AboutMih(arguments: AboutArguments(personalSelected, index)); + return AboutMih(); }, ), // ========================== Mzansi Profile Personal ================================== @@ -166,15 +153,13 @@ class MihGoRouter { path: MihGoRouterPaths.mzansiProfileManage, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: mzansiProfileManage"); - final AppProfileUpdateArguments? args = - state.extra as AppProfileUpdateArguments?; - if (args == null) { + if (context.watch().user == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); return const SizedBox.shrink(); } - return MzansiProfile(arguments: args); + return MzansiProfile(); }, ), GoRoute( @@ -182,14 +167,15 @@ class MihGoRouter { path: MihGoRouterPaths.mzansiProfileView, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: mzansiProfileView"); - final AppUser? user = state.extra as AppUser?; - if (user == null) { + MzansiDirectoryProvider directoryProvider = + context.read(); + if (directoryProvider.selectedUser == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); return const SizedBox.shrink(); } - return MzansiProfileView(user: user); + return MzansiProfileView(); }, ), // ========================== Mzansi Profile Business ================================== @@ -198,8 +184,7 @@ class MihGoRouter { path: MihGoRouterPaths.businessProfileManage, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: businessProfileManage"); - final BusinessArguments? args = state.extra as BusinessArguments?; - if (args == null) { + if (context.watch().business == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); @@ -207,7 +192,6 @@ class MihGoRouter { } return MzansiBusinessProfile( key: UniqueKey(), - arguments: args, ); }, ), @@ -218,9 +202,10 @@ class MihGoRouter { KenLogger.success("MihGoRouter: businessProfileView"); String? businessId = state.uri.queryParameters['business_id']; KenLogger.success("businessId: $businessId"); - final BusinessViewArguments? args = - state.extra as BusinessViewArguments?; - if (args == null && businessId == null) { + MzansiDirectoryProvider directoryProvider = + context.read(); + if (directoryProvider.selectedBusiness == null && + businessId == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); @@ -228,7 +213,6 @@ class MihGoRouter { } return MzansiBusinessProfileView( key: UniqueKey(), - arguments: args, businessId: businessId, ); }, @@ -238,8 +222,7 @@ class MihGoRouter { path: MihGoRouterPaths.businessProfileSetup, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: businessProfileSetup"); - final AppUser? signedInUser = state.extra as AppUser?; - return ProfileBusinessAdd(signedInUser: signedInUser!); + return MzansiSetUpBusinessProfile(); }, ), // ========================== MIH Calculator ================================== @@ -248,12 +231,7 @@ class MihGoRouter { path: MihGoRouterPaths.calculator, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: mihCalculator"); - final bool? personalSelected = state.extra as bool?; - bool personal = true; - if (personalSelected != null) { - personal = personalSelected; - } - return MIHCalculator(personalSelected: personal); + return MIHCalculator(); }, ), // ========================== MIH Calculator ================================== @@ -262,8 +240,7 @@ class MihGoRouter { path: MihGoRouterPaths.calendar, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: mihCalendar"); - final CalendarArguments? args = state.extra as CalendarArguments?; - if (args == null) { + if (context.watch().user == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); @@ -271,7 +248,6 @@ class MihGoRouter { } return MzansiCalendar( key: UniqueKey(), - arguments: args, ); }, ), @@ -281,14 +257,13 @@ class MihGoRouter { path: MihGoRouterPaths.mzansiAi, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: mzansiAi"); - final MzansiAiArguments? args = state.extra as MzansiAiArguments?; - if (args == null) { + if (context.watch().user == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); return const SizedBox.shrink(); } - return MzansiAi(arguments: args); + return MzansiAi(); }, ), // ========================== Mzansi Wallet ================================== @@ -297,8 +272,7 @@ class MihGoRouter { path: MihGoRouterPaths.mzansiWallet, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: mzansiWallet"); - final WalletArguments? args = state.extra as WalletArguments?; - if (args == null) { + if (context.watch().user == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); @@ -306,7 +280,6 @@ class MihGoRouter { } return MihWallet( key: UniqueKey(), - arguments: args, ); }, ), @@ -347,8 +320,8 @@ class MihGoRouter { name: "mihAccess", path: MihGoRouterPaths.mihAccess, builder: (BuildContext context, GoRouterState state) { - final AppUser? signedInUser = state.extra as AppUser?; - if (signedInUser == null) { + KenLogger.success("MihGoRouter: mihAccess"); + if (context.watch().user == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); @@ -356,7 +329,6 @@ class MihGoRouter { } return MihAccess( key: UniqueKey(), - signedInUser: signedInUser, ); }, ), @@ -365,44 +337,36 @@ class MihGoRouter { name: "patientProfile", path: MihGoRouterPaths.patientProfile, builder: (BuildContext context, GoRouterState state) { - final PatientViewArguments? args = - state.extra as PatientViewArguments?; - if (args == null) { + KenLogger.success("MihGoRouter: patientProfile"); + if (context.watch().user == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); return const SizedBox.shrink(); } - return AddOrViewPatient( - key: UniqueKey(), - arguments: args, - ); + return PatientProfile(); }, ), GoRoute( - name: "patientProfileEdit", - path: MihGoRouterPaths.patientProfileEdit, + name: "patientProfileSetup", + path: MihGoRouterPaths.patientProfileSetup, builder: (BuildContext context, GoRouterState state) { - final PatientEditArguments? args = - state.extra as PatientEditArguments?; - if (args == null) { + KenLogger.success("MihGoRouter: patientProfileSetup"); + if (context.watch().user == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); return const SizedBox.shrink(); } - return EditPatient( - signedInUser: args.signedInUser, - selectedPatient: args.selectedPatient, - ); + return PatientSetUp(); }, ), GoRoute( name: "patientManager", path: MihGoRouterPaths.patientManager, builder: (BuildContext context, GoRouterState state) { - final PatManagerArguments? args = state.extra as PatManagerArguments?; - if (args == null) { + KenLogger.success("MihGoRouter: patientManager"); + if (context.watch().business == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); @@ -410,7 +374,6 @@ class MihGoRouter { } return PatManager( key: UniqueKey(), - arguments: args, ); }, ), @@ -418,15 +381,14 @@ class MihGoRouter { name: "patientManagerPatient", path: MihGoRouterPaths.patientManagerPatient, builder: (BuildContext context, GoRouterState state) { - final PatientViewArguments? args = - state.extra as PatientViewArguments?; - if (args == null) { + KenLogger.success("MihGoRouter: patientManagerPatient"); + if (context.watch().user == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); return const SizedBox.shrink(); } - return PatientProfile(arguments: args); + return PatientProfile(); }, ), // ========================== Mzansi Directory ================================== @@ -434,15 +396,14 @@ class MihGoRouter { name: "mzansiDirectory", path: MihGoRouterPaths.mzansiDirectory, builder: (BuildContext context, GoRouterState state) { - final MzansiDirectoryArguments? args = - state.extra as MzansiDirectoryArguments?; - if (args == null) { + KenLogger.success("MihGoRouter: mzansiDirectory"); + if (context.watch().user == null) { WidgetsBinding.instance.addPostFrameCallback((_) { context.go(MihGoRouterPaths.mihHome); }); return const SizedBox.shrink(); } - return MzansiDirectory(arguments: args); + return MzansiDirectory(); }, ), // ========================== End ================================== @@ -450,6 +411,7 @@ class MihGoRouter { name: "fileViewer", path: MihGoRouterPaths.fileViewer, builder: (BuildContext context, GoRouterState state) { + KenLogger.success("MihGoRouter: fileViewer"); final FileViewArguments? args = state.extra as FileViewArguments?; return FullScreenFileViewer(arguments: args!); }, @@ -458,11 +420,27 @@ class MihGoRouter { name: "printPreview", path: MihGoRouterPaths.printPreview, builder: (BuildContext context, GoRouterState state) { + KenLogger.success("MihGoRouter: printPreview"); final PrintPreviewArguments? args = state.extra as PrintPreviewArguments?; return MIHPrintPreview(arguments: args!); }, ), + // ========================== MIH Minesweeper ================================== + GoRoute( + name: "mihMinesweeper", + path: MihGoRouterPaths.mihMineSweeper, + builder: (BuildContext context, GoRouterState state) { + KenLogger.success("MihGoRouter: mihMineSweeper"); + if (context.watch().user == null) { + WidgetsBinding.instance.addPostFrameCallback((_) { + context.go(MihGoRouterPaths.mihHome); + }); + return const SizedBox.shrink(); + } + return MihMineSweeper(); + }, + ), // ========================== End ================================== // GoRoute( // name: "notifications", diff --git a/Frontend/lib/mih_packages/about_mih/about_mih.dart b/Frontend/lib/mih_packages/about_mih/about_mih.dart index e18dcf45..07f69340 100644 --- a/Frontend/lib/mih_packages/about_mih/about_mih.dart +++ b/Frontend/lib/mih_packages/about_mih/about_mih.dart @@ -1,19 +1,18 @@ import 'package:go_router/go_router.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/about_mih_provider.dart'; import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tools/mih_%20attributes.dart'; import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tools/mih_info.dart'; import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tools/mih_privacy_policy.dart'; import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tools/mih_terms_of_service.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class AboutMih extends StatefulWidget { - final AboutArguments? arguments; const AboutMih({ super.key, - this.arguments, }); @override @@ -21,21 +20,9 @@ class AboutMih extends StatefulWidget { } class _AboutMihState extends State { - late int _selcetedIndex; - late bool _personalSelected; - @override void initState() { super.initState(); - setState(() { - if (widget.arguments == null) { - _selcetedIndex = 0; - _personalSelected = true; - } else { - _selcetedIndex = widget.arguments!.packageIndex!; - _personalSelected = widget.arguments!.personalSelected; - } - }); } @override @@ -45,12 +32,9 @@ class _AboutMihState extends State { appTools: getTools(), appBody: getToolBody(), appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); - // print("Index: $_selcetedIndex"); + selectedbodyIndex: context.watch().toolIndex, + onIndexChange: (newIndex) { + context.read().setToolIndex(newIndex); }, ); } @@ -62,7 +46,6 @@ class _AboutMihState extends State { onTap: () { context.goNamed( 'mihHome', - extra: _personalSelected, ); FocusScope.of(context).unfocus(); }, @@ -72,28 +55,20 @@ class _AboutMihState extends State { MihPackageTools getTools() { Map temp = {}; temp[const Icon(Icons.info)] = () { - setState(() { - _selcetedIndex = 0; - }); + context.read().setToolIndex(0); }; temp[const Icon(Icons.policy)] = () { - setState(() { - _selcetedIndex = 1; - }); + context.read().setToolIndex(1); }; temp[const Icon(Icons.design_services)] = () { - setState(() { - _selcetedIndex = 2; - }); + context.read().setToolIndex(2); }; temp[const Icon(Icons.star_rounded)] = () { - setState(() { - _selcetedIndex = 3; - }); + context.read().setToolIndex(3); }; return MihPackageTools( tools: temp, - selcetedIndex: _selcetedIndex, + selcetedIndex: context.watch().toolIndex, ); } diff --git a/Frontend/lib/mih_packages/about_mih/package_tile/about_mih_tile.dart b/Frontend/lib/mih_packages/about_mih/package_tile/about_mih_tile.dart index 28b03444..945a4122 100644 --- a/Frontend/lib/mih_packages/about_mih/package_tile/about_mih_tile.dart +++ b/Frontend/lib/mih_packages/about_mih/package_tile/about_mih_tile.dart @@ -1,6 +1,5 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; @@ -8,11 +7,9 @@ import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; class AboutMihTile extends StatefulWidget { final double packageSize; - final bool personalSelected; const AboutMihTile({ super.key, required this.packageSize, - required this.personalSelected, }); @override @@ -26,10 +23,6 @@ class _AboutMihTileState extends State { onTap: () { context.goNamed( "aboutMih", - extra: AboutArguments( - widget.personalSelected, - 0, - ), ); // Navigator.of(context).pushNamed( // '/about', diff --git a/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart b/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart index 98f090aa..d3456a20 100644 --- a/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart +++ b/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart @@ -506,8 +506,8 @@ class _MihInfoState extends State { void shareMIHLink(BuildContext context, String message, String link) { String shareText = "$message: $link"; - Share.share( - shareText, + SharePlus.instance.share( + ShareParams(text: shareText), ); } @@ -610,7 +610,7 @@ class _MihInfoState extends State { ), const SizedBox(width: 10), Text( - "Users", + "People", textAlign: TextAlign.center, style: TextStyle( fontWeight: FontWeight.normal, diff --git a/Frontend/lib/mih_packages/access_review/builder/build_business_access_list.dart b/Frontend/lib/mih_packages/access_review/builder/build_business_access_list.dart index 2aca7f2c..782c75a3 100644 --- a/Frontend/lib/mih_packages/access_review/builder/build_business_access_list.dart +++ b/Frontend/lib/mih_packages/access_review/builder/build_business_access_list.dart @@ -2,7 +2,10 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_access_controls_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; @@ -10,18 +13,15 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ 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_warning_message.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart'; +import 'package:provider/provider.dart'; class BuildBusinessAccessList extends StatefulWidget { - final List patientAccessList; - final AppUser signedInUser; + final String filterText; final void Function()? onSuccessUpate; const BuildBusinessAccessList({ super.key, - required this.patientAccessList, - required this.signedInUser, + required this.filterText, required this.onSuccessUpate, }); @@ -60,18 +60,20 @@ class _BuildPatientsListState extends State { ); } - Widget displayQueue(int index) { - String line1 = - "Business Name: ${widget.patientAccessList[index].requested_by}"; + Widget displayQueue( + MzansiProfileProvider mzansiProfileProvider, + MihAccessControllsProvider accessProvider, + int index, + List filteredList) { + String line1 = "Business Name: ${filteredList[index].requested_by}"; String line2 = ""; line2 += - "Request Date: ${widget.patientAccessList[index].requested_on.substring(0, 16).replaceAll("T", " ")}\n"; - line2 += - "Profile Type: ${widget.patientAccessList[index].type.toUpperCase()}\n"; + "Request Date: ${filteredList[index].requested_on.substring(0, 16).replaceAll("T", " ")}\n"; + line2 += "Profile Type: ${filteredList[index].type.toUpperCase()}\n"; //subtitle += "Business Type: ${widget.patientAccessList[index].type}\n"; String line3 = "Status: "; - String access = widget.patientAccessList[index].status.toUpperCase(); + String access = filteredList[index].status.toUpperCase(); TextSpan accessWithColour; if (access == "APPROVED") { @@ -118,7 +120,7 @@ class _BuildPatientsListState extends State { // ), // ), onTap: () { - viewApprovalPopUp(index); + viewApprovalPopUp(mzansiProfileProvider, accessProvider, index); }, // trailing: Icon( // Icons.arrow_forward, @@ -153,23 +155,24 @@ class _BuildPatientsListState extends State { } } - void viewApprovalPopUp(int index) { + void viewApprovalPopUp(MzansiProfileProvider mzansiProfileProvider, + MihAccessControllsProvider accessProvider, int index) { String subtitle = - "Business Name: ${widget.patientAccessList[index].requested_by}\n"; + "Business Name: ${accessProvider.accessList![index].requested_by}\n"; subtitle += - "Requested Date: ${widget.patientAccessList[index].requested_on.substring(0, 16).replaceAll("T", " ")}\n"; + "Requested Date: ${accessProvider.accessList![index].requested_on.substring(0, 16).replaceAll("T", " ")}\n"; subtitle += - "Profile Type: ${widget.patientAccessList[index].type.toUpperCase()}\n"; + "Profile Type: ${accessProvider.accessList![index].type.toUpperCase()}\n"; subtitle += - "Status: ${widget.patientAccessList[index].status.toUpperCase()}"; - if (widget.patientAccessList[index].status == 'pending') { + "Status: ${accessProvider.accessList![index].status.toUpperCase()}"; + if (accessProvider.accessList![index].status == 'pending') { // "\nYou are about to approve an access request to your patient profile.\nPlease be aware that once approved, ${widget.patientAccessList[index].requested_by} will have access to your profile forever and will be able to contribute to it.\nIf you are unsure about an upcoming appointment with ${widget.patientAccessList[index].requested_by}, please contact *Add Number here* for clarification before approving this request."; } else { subtitle += - "\nActioned By: ${widget.patientAccessList[index].approved_by}\n"; + "\nActioned By: ${accessProvider.accessList![index].approved_by}\n"; subtitle += - "Actioned On: ${widget.patientAccessList[index].approved_on.substring(0, 16).replaceAll("T", " ")}"; + "Actioned On: ${accessProvider.accessList![index].approved_on.substring(0, 16).replaceAll("T", " ")}"; // subtitle += // "You have approved this access request to your patient profile.\nPlease be aware that once approved, ${widget.patientAccessList[index].requested_by} will have access to your profile forever and will be able to contribute to it."; } @@ -199,7 +202,7 @@ class _BuildPatientsListState extends State { ), const SizedBox(height: 20.0), Visibility( - visible: widget.patientAccessList[index].status == 'pending', + visible: accessProvider.accessList![index].status == 'pending', child: Column( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.start, @@ -271,7 +274,7 @@ class _BuildPatientsListState extends State { ), ), Visibility( - visible: widget.patientAccessList[index].status == 'approved', + visible: accessProvider.accessList![index].status == 'approved', child: Column( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.start, @@ -338,7 +341,7 @@ class _BuildPatientsListState extends State { height: 20, ), Visibility( - visible: widget.patientAccessList[index].status == 'pending', + visible: accessProvider.accessList![index].status == 'pending', child: Wrap( runSpacing: 10, spacing: 10, @@ -348,15 +351,20 @@ class _BuildPatientsListState extends State { print("request declined"); int statusCode = await MihAccessControlsServices() .updatePatientAccessAPICall( - widget.patientAccessList[index].business_id, - widget.patientAccessList[index].requested_by, - widget.patientAccessList[index].app_id, + accessProvider.accessList![index].business_id, + accessProvider.accessList![index].requested_by, + accessProvider.accessList![index].app_id, "declined", - "${widget.signedInUser.fname} ${widget.signedInUser.lname}", - widget.signedInUser, + "${mzansiProfileProvider.user!.fname} ${mzansiProfileProvider.user!.lname}", + mzansiProfileProvider.user!, context, ); if (statusCode == 200) { + await MihAccessControlsServices() + .getBusinessAccessListOfPatient( + mzansiProfileProvider.user!.app_id, + accessProvider, + ); context.pop(); successPopUp("Successfully Actioned Request", "You have successfully Declined access request"); @@ -384,15 +392,20 @@ class _BuildPatientsListState extends State { print("request approved"); int statusCode = await MihAccessControlsServices() .updatePatientAccessAPICall( - widget.patientAccessList[index].business_id, - widget.patientAccessList[index].requested_by, - widget.patientAccessList[index].app_id, + accessProvider.accessList![index].business_id, + accessProvider.accessList![index].requested_by, + accessProvider.accessList![index].app_id, "approved", - "${widget.signedInUser.fname} ${widget.signedInUser.lname}", - widget.signedInUser, + "${mzansiProfileProvider.user!.fname} ${mzansiProfileProvider.user!.lname}", + mzansiProfileProvider.user!, context, ); if (statusCode == 200) { + await MihAccessControlsServices() + .getBusinessAccessListOfPatient( + mzansiProfileProvider.user!.app_id, + accessProvider, + ); context.pop(); successPopUp("Successfully Actioned Request", "You have successfully Accepted access request"); @@ -487,6 +500,16 @@ class _BuildPatientsListState extends State { ); } + List filterAccessList(List accessList) { + if (widget.filterText == "All") { + return accessList; + } + return accessList + .where((item) => + item.status.toLowerCase() == widget.filterText.toLowerCase()) + .toList(); + } + @override void dispose() { super.dispose(); @@ -500,21 +523,30 @@ class _BuildPatientsListState extends State { height = size.height; }); checkScreenSize(); - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - separatorBuilder: (BuildContext context, index) { - return Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + return Consumer2( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, + MihAccessControllsProvider accessProvider, + Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, index) { + return Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + itemCount: filterAccessList(accessProvider.accessList!).length, + itemBuilder: (context, index) { + //final patient = widget.patients[index].id_no.contains(widget.searchString); + //print(index); + final filteredList = filterAccessList(accessProvider.accessList!); + return displayQueue( + mzansiProfileProvider, accessProvider, index, filteredList); + }, ); }, - itemCount: widget.patientAccessList.length, - itemBuilder: (context, index) { - //final patient = widget.patients[index].id_no.contains(widget.searchString); - //print(index); - return displayQueue(index); - }, ); } } diff --git a/Frontend/lib/mih_packages/access_review/mih_access.dart b/Frontend/lib/mih_packages/access_review/mih_access.dart index 3812784a..73d4e325 100644 --- a/Frontend/lib/mih_packages/access_review/mih_access.dart +++ b/Frontend/lib/mih_packages/access_review/mih_access.dart @@ -2,15 +2,14 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart'; import 'package:mzansi_innovation_hub/mih_packages/access_review/package_tools/mih_access_requests.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MihAccess extends StatefulWidget { - final AppUser signedInUser; const MihAccess({ super.key, - required this.signedInUser, }); @override @@ -18,7 +17,6 @@ class MihAccess extends StatefulWidget { } class _MihAccessState extends State { - int _selcetedIndex = 0; @override Widget build(BuildContext context) { return MihPackage( @@ -26,12 +24,9 @@ class _MihAccessState extends State { appTools: getTools(), appBody: getToolBody(), appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, + selectedbodyIndex: context.watch().toolIndex, onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); - print("Index: $_selcetedIndex"); + context.read().setToolIndex(newValue); }, ); } @@ -43,7 +38,6 @@ class _MihAccessState extends State { onTap: () { context.goNamed( 'mihHome', - extra: true, ); FocusScope.of(context).unfocus(); }, @@ -53,21 +47,17 @@ class _MihAccessState extends State { MihPackageTools getTools() { Map temp = {}; temp[const Icon(Icons.people)] = () { - setState(() { - _selcetedIndex = 0; - }); + context.read().setToolIndex(0); }; return MihPackageTools( tools: temp, - selcetedIndex: _selcetedIndex, + selcetedIndex: context.watch().toolIndex, ); } List getToolBody() { List toolBodies = [ - MihAccessRequest( - signedInUser: widget.signedInUser, - ), + MihAccessRequest(), ]; return toolBodies; } diff --git a/Frontend/lib/mih_packages/access_review/package_tile/mih_access_tile.dart b/Frontend/lib/mih_packages/access_review/package_tile/mih_access_tile.dart index 1e5a4ea7..8574ef9e 100644 --- a/Frontend/lib/mih_packages/access_review/package_tile/mih_access_tile.dart +++ b/Frontend/lib/mih_packages/access_review/package_tile/mih_access_tile.dart @@ -2,17 +2,14 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; class MihAccessTile extends StatefulWidget { - final AppUser signedInUser; final double packageSize; const MihAccessTile({ super.key, - required this.signedInUser, required this.packageSize, }); @@ -28,7 +25,6 @@ class _MihAccessTileState extends State { onTap: () { context.goNamed( "mihAccess", - extra: widget.signedInUser, ); // Navigator.of(context).pushNamed( // '/mih-access', diff --git a/Frontend/lib/mih_packages/access_review/package_tools/mih_access_requests.dart b/Frontend/lib/mih_packages/access_review/package_tools/mih_access_requests.dart index aca607c2..1fc2f9d8 100644 --- a/Frontend/lib/mih_packages/access_review/package_tools/mih_access_requests.dart +++ b/Frontend/lib/mih_packages/access_review/package_tools/mih_access_requests.dart @@ -1,28 +1,24 @@ import 'package:go_router/go_router.dart'; import 'package:ken_logger/ken_logger.dart'; -import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_action.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_header.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:mzansi_innovation_hub/mih_packages/access_review/builder/build_business_access_list.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_access_controls_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:flutter/material.dart'; -import '../../../mih_services/mih_service_calls.dart'; -import '../../../mih_components/mih_layout/mih_action.dart'; -import '../../../mih_components/mih_layout/mih_header.dart'; -import '../../../mih_components/mih_pop_up_messages/mih_loading_circle.dart'; -import '../../../mih_config/mih_env.dart'; -import '../../../mih_components/mih_objects/app_user.dart'; -import '../../../mih_components/mih_objects/patient_access.dart'; -import '../builder/build_business_access_list.dart'; +import 'package:provider/provider.dart'; class MihAccessRequest extends StatefulWidget { - final AppUser signedInUser; - const MihAccessRequest({ super.key, - required this.signedInUser, }); @override @@ -31,7 +27,7 @@ class MihAccessRequest extends StatefulWidget { class _MihAccessRequestState extends State { TextEditingController filterController = TextEditingController(); - + bool isLoading = true; String baseUrl = AppEnviroment.baseApiUrl; String errorCode = ""; @@ -41,35 +37,8 @@ class _MihAccessRequestState extends State { bool forceRefresh = false; late String selectedDropdown; - late Future> accessList; - - // Future> fetchAccessRequests() async { - // //print("Patien manager page: $endpoint"); - // final response = await http.get( - // Uri.parse("$baseUrl/access-requests/${widget.signedInUser.app_id}")); - // // print("Here"); - // // print("Body: ${response.body}"); - // // print("Code: ${response.statusCode}"); - // errorCode = response.statusCode.toString(); - // errorBody = response.body; - - // if (response.statusCode == 200) { - // //print("Here1"); - // Iterable l = jsonDecode(response.body); - // //print("Here2"); - // List patientQueue = List.from( - // l.map((model) => AccessRequest.fromJson(model))); - // //print("Here3"); - // //print(patientQueue); - // return patientQueue; - // } else { - // throw Exception('failed to load patients'); - // } - // } - List filterSearchResults(List accessList) { List templist = []; - for (var item in accessList) { if (filterController.text == "All") { templist.add(item); @@ -83,16 +52,24 @@ class _MihAccessRequestState extends State { } void refreshList() { + MzansiProfileProvider mzansiProfileProvider = + context.read(); + MihAccessControllsProvider accessProvider = + context.read(); if (forceRefresh == true) { + MihAccessControlsServices().getBusinessAccessListOfPatient( + mzansiProfileProvider.user!.app_id, + accessProvider, + ); setState(() { - accessList = MIHApiCalls.getBusinessAccessListOfPatient( - widget.signedInUser.app_id); forceRefresh = false; }); } else if (selectedDropdown != filterController.text) { + MihAccessControlsServices().getBusinessAccessListOfPatient( + mzansiProfileProvider.user!.app_id, + accessProvider, + ); setState(() { - accessList = MIHApiCalls.getBusinessAccessListOfPatient( - widget.signedInUser.app_id); selectedDropdown = filterController.text; }); } @@ -131,166 +108,92 @@ class _MihAccessRequestState extends State { } Widget getBody() { - return MihSingleChildScroll( - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisSize: MainAxisSize.max, + return Consumer2( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, + MihAccessControllsProvider accessProvider, + Widget? child) { + if (isLoading) { + return const Center( + child: Mihloadingcircle(), + ); + } + return MihSingleChildScroll( + child: Column( children: [ - Flexible( - child: MihDropdownField( - controller: filterController, - hintText: "Access Type", - dropdownOptions: const [ - "All", - "Approved", - "Pending", - "Declined", - "Cancelled", - ], - requiredText: true, - editable: true, - enableSearch: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - ), - IconButton( - iconSize: 35, - onPressed: () { - setState(() { - forceRefresh = true; - }); - KenLogger.warning("Refreshing Access List"); - refreshList(); - }, - icon: const Icon( - Icons.refresh, - ), - ), - ], - ), - const SizedBox(height: 10), - FutureBuilder( - future: accessList, - builder: (context, snapshot) { - //print("patient Queue List ${snapshot.hasData}"); - if (snapshot.connectionState == ConnectionState.waiting) { - return const Mihloadingcircle(); - } else if (snapshot.connectionState == ConnectionState.done) { - List accessRequestList; - accessRequestList = filterSearchResults(snapshot.requireData); - if (accessRequestList.isNotEmpty) { - return BuildBusinessAccessList( - signedInUser: widget.signedInUser, - patientAccessList: accessRequestList, - onSuccessUpate: () { + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: MihDropdownField( + controller: filterController, + hintText: "Access Type", + dropdownOptions: const [ + "All", + "Approved", + "Pending", + "Declined", + "Cancelled", + ], + requiredText: true, + editable: true, + enableSearch: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + ), + IconButton( + iconSize: 35, + onPressed: () { setState(() { forceRefresh = true; }); + KenLogger.warning("Refreshing Access List"); refreshList(); }, - ); - } else { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 50), - Icon( - MihIcons.accessControl, - size: 165, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - const SizedBox(height: 10), - Text( - "No access has been granted to your MIH Profile", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - // const SizedBox(height: 10), - // Center( - // child: RichText( - // textAlign: TextAlign.center, - // text: TextSpan( - // style: TextStyle( - // fontSize: 20, - // fontWeight: FontWeight.normal, - // color: MzansiInnovationHub.of(context)! - // .theme - // .secondaryColor(), - // ), - // children: [ - // TextSpan(text: "Press "), - // WidgetSpan( - // alignment: PlaceholderAlignment.middle, - // child: Icon( - // Icons.menu, - // size: 20, - // color: MzansiInnovationHub.of(context)! - // .theme - // .secondaryColor(), - // ), - // ), - // TextSpan( - // text: " to add your first loyalty card."), - // ], - // ), - // ), - // ), - ], + icon: const Icon( + Icons.refresh, ), - ); - // return Center( - // child: Text( - // "No Request have been made.", - // style: TextStyle( - // fontSize: 25, - // color: MzansiInnovationHub.of(context)! - // .theme - // .messageTextColor()), - // textAlign: TextAlign.center, - // ), - // ); - } - - // return Expanded( - // child: displayAccessRequestList(accessRequestList), - // ); - } else { - return Center( - child: Text( - "$errorCode: Error pulling Patients Data\n$baseUrl/queue/patients/\n$errorBody", - style: TextStyle( - fontSize: 25, - color: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark")), - textAlign: TextAlign.center, ), - ); - } - }, + ], + ), + const SizedBox(height: 10), + BuildBusinessAccessList( + filterText: filterController.text, + onSuccessUpate: () { + setState(() { + forceRefresh = true; + }); + refreshList(); + }, + ), + ], ), - ], - ), + ); + }, ); } + Future initiasizeAccessList() async { + MzansiProfileProvider mzansiProfileProvider = + context.read(); + MihAccessControllsProvider accessProvider = + context.read(); + setState(() { + isLoading = true; + }); + await MihAccessControlsServices().getBusinessAccessListOfPatient( + mzansiProfileProvider.user!.app_id, + accessProvider, + ); + setState(() { + isLoading = false; + }); + } + @override void dispose() { filterController.dispose(); @@ -302,9 +205,8 @@ class _MihAccessRequestState extends State { selectedDropdown = "All"; filterController.text = "All"; filterController.addListener(refreshList); - setState(() { - accessList = MIHApiCalls.getBusinessAccessListOfPatient( - widget.signedInUser.app_id); + WidgetsBinding.instance.addPostFrameCallback((_) async { + await initiasizeAccessList(); }); super.initState(); } diff --git a/Frontend/lib/mih_packages/calculator/mih_calculator.dart b/Frontend/lib/mih_packages/calculator/mih_calculator.dart index cf52264f..e0ed5add 100644 --- a/Frontend/lib/mih_packages/calculator/mih_calculator.dart +++ b/Frontend/lib/mih_packages/calculator/mih_calculator.dart @@ -2,16 +2,18 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calculator_provider.dart'; import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tools/currency_exchange_rate.dart'; import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tools/simple_calc.dart'; import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tools/tip_calc.dart'; import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_currency_exchange_rate_services.dart'; +import 'package:provider/provider.dart'; class MIHCalculator extends StatefulWidget { - final bool personalSelected; const MIHCalculator({ super.key, - required this.personalSelected, }); @override @@ -19,7 +21,18 @@ class MIHCalculator extends StatefulWidget { } class _MIHCalculatorState extends State { - int _selectedIndex = 0; + Future getCurrencyCodeList() async { + await MihCurrencyExchangeRateServices.getCurrencyCodeList(context); + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) async { + context.read().loadBannerAd(); + await getCurrencyCodeList(); + }); + } @override Widget build(BuildContext context) { @@ -28,12 +41,9 @@ class _MIHCalculatorState extends State { appTools: getTools(), appBody: getToolBody(), appToolTitles: getToolTitle(), - selectedbodyIndex: _selectedIndex, - onIndexChange: (newValue) { - setState(() { - _selectedIndex = newValue; - }); - print("Index: $_selectedIndex"); + selectedbodyIndex: context.watch().toolIndex, + onIndexChange: (newIndex) { + context.read().setToolIndex(newIndex); }, ); } @@ -45,7 +55,6 @@ class _MIHCalculatorState extends State { onTap: () { context.goNamed( 'mihHome', - extra: widget.personalSelected, ); FocusScope.of(context).unfocus(); }, @@ -55,23 +64,17 @@ class _MIHCalculatorState extends State { MihPackageTools getTools() { Map temp = {}; temp[const Icon(Icons.calculate)] = () { - setState(() { - _selectedIndex = 0; - }); + context.read().setToolIndex(0); }; temp[const Icon(Icons.money)] = () { - setState(() { - _selectedIndex = 1; - }); + context.read().setToolIndex(1); }; temp[const Icon(Icons.currency_exchange)] = () { - setState(() { - _selectedIndex = 2; - }); + context.read().setToolIndex(2); }; return MihPackageTools( tools: temp, - selcetedIndex: _selectedIndex, + selcetedIndex: context.watch().toolIndex, ); } diff --git a/Frontend/lib/mih_packages/calculator/package_tiles/mih_calculator_tile.dart b/Frontend/lib/mih_packages/calculator/package_tiles/mih_calculator_tile.dart index 58c42944..a771df6b 100644 --- a/Frontend/lib/mih_packages/calculator/package_tiles/mih_calculator_tile.dart +++ b/Frontend/lib/mih_packages/calculator/package_tiles/mih_calculator_tile.dart @@ -6,12 +6,10 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; class MihCalculatorTile extends StatefulWidget { - final bool personalSelected; final double packageSize; const MihCalculatorTile({ super.key, - required this.personalSelected, required this.packageSize, }); @@ -26,12 +24,7 @@ class _MihCalculatorTileState extends State { onTap: () { context.goNamed( "mihCalculator", - extra: widget.personalSelected, ); - // Navigator.of(context).pushNamed( - // '/calculator', - // arguments: widget.personalSelected, - // ); }, appName: "Calculator", appIcon: Icon( diff --git a/Frontend/lib/mih_packages/calculator/package_tools/currency_exchange_rate.dart b/Frontend/lib/mih_packages/calculator/package_tools/currency_exchange_rate.dart index a91104ec..b0680632 100644 --- a/Frontend/lib/mih_packages/calculator/package_tools/currency_exchange_rate.dart +++ b/Frontend/lib/mih_packages/calculator/package_tools/currency_exchange_rate.dart @@ -9,11 +9,13 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calculator_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_currency_exchange_rate_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; class CurrencyExchangeRate extends StatefulWidget { const CurrencyExchangeRate({super.key}); @@ -28,8 +30,6 @@ class _CurrencyExchangeRateState extends State { final TextEditingController _toCurrencyController = TextEditingController(); final TextEditingController _fromAmountController = TextEditingController(); final TextEditingController _toAmountController = TextEditingController(); - late Future> availableCurrencies; - MihBannerAd _bannerAd = MihBannerAd(); Future submitForm() async { String fromCurrencyCode = _fromCurrencyController.text.split(" - ")[0]; @@ -67,9 +67,7 @@ class _CurrencyExchangeRateState extends State { fullscreen: false, windowTitle: "Calculation Results", onWindowTapClose: () { - setState(() { - _bannerAd = MihBannerAd(); - }); + context.read().loadBannerAd(); Navigator.pop(context); }, windowBody: Column( @@ -160,7 +158,9 @@ class _CurrencyExchangeRateState extends State { ], ), SizedBox(height: 10), - SizedBox(child: _bannerAd), + Consumer(builder: (context, bannerAdDisplay, child) { + return MihBannerAd(); + }), ], ), ), @@ -275,7 +275,6 @@ class _CurrencyExchangeRateState extends State { @override void initState() { super.initState(); - availableCurrencies = MihCurrencyExchangeRateServices.getCurrencyCodeList(); } @override @@ -289,177 +288,155 @@ class _CurrencyExchangeRateState extends State { } Widget getBody(double width) { - return FutureBuilder( - future: availableCurrencies, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Mihloadingcircle(); - } else if (snapshot.connectionState == ConnectionState.done) { - return MihSingleChildScroll( - child: Padding( - padding: MzansiInnovationHub.of(context)!.theme.screenType == - "desktop" + return Consumer( + builder: (context, calculatorProvider, child) { + return MihSingleChildScroll( + child: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" ? EdgeInsets.symmetric(horizontal: width * 0.2) : EdgeInsets.symmetric(horizontal: width * 0.075), - child: Column( - children: [ - MihForm( - formKey: _formKey, - formFields: [ - MihTextFormField( - fillColor: MihColors.getSecondaryColor( + child: Column( + children: [ + MihForm( + formKey: _formKey, + formFields: [ + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: _fromAmountController, + multiLineInput: false, + requiredText: true, + hintText: "Currency Amount", + numberMode: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10), + MihDropdownField( + controller: _fromCurrencyController, + hintText: "From", + dropdownOptions: calculatorProvider.availableCurrencies, + editable: true, + enableSearch: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + requiredText: true, + ), + const SizedBox(height: 10), + MihDropdownField( + controller: _toCurrencyController, + hintText: "To", + dropdownOptions: calculatorProvider.availableCurrencies, + editable: true, + enableSearch: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + requiredText: true, + ), + const SizedBox(height: 15), + RichText( + textAlign: TextAlign.left, + text: TextSpan( + style: TextStyle( + fontSize: 15, + color: MihColors.getRedColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: _fromAmountController, - multiLineInput: false, - requiredText: true, - hintText: "Currency Amount", - numberMode: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, ), - const SizedBox(height: 10), - MihDropdownField( - controller: _fromCurrencyController, - hintText: "From", - dropdownOptions: snapshot.data!, - editable: true, - enableSearch: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - requiredText: true, - ), - const SizedBox(height: 10), - MihDropdownField( - controller: _toCurrencyController, - hintText: "To", - dropdownOptions: snapshot.data!, - editable: true, - enableSearch: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - requiredText: true, - ), - const SizedBox(height: 15), - RichText( - textAlign: TextAlign.left, - text: TextSpan( + children: [ + const TextSpan( + text: "* Experimental Feature: Please review "), + TextSpan( + text: "Diclaimer", style: TextStyle( - fontSize: 15, - color: MihColors.getRedColor( + decoration: TextDecoration.underline, + color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontWeight: FontWeight.bold, ), - children: [ - const TextSpan( - text: - "* Experimental Feature: Please review "), - TextSpan( - text: "Diclaimer", - style: TextStyle( - decoration: TextDecoration.underline, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - fontWeight: FontWeight.bold, - ), - recognizer: TapGestureRecognizer() - ..onTap = () { - displayDisclaimer(); - }, - ), - const TextSpan(text: " before use."), - ], + recognizer: TapGestureRecognizer() + ..onTap = () { + displayDisclaimer(); + }, ), - ), - const SizedBox(height: 25), - Center( - child: Wrap( - spacing: 10, - runSpacing: 10, - children: [ - MihButton( - onPressed: () { - if (_formKey.currentState!.validate()) { - submitForm(); - FocusScope.of(context) - .requestFocus(FocusNode()); - } else { - MihAlertServices() - .formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( + const TextSpan(text: " before use."), + ], + ), + ), + const SizedBox(height: 25), + Center( + child: Wrap( + spacing: 10, + runSpacing: 10, + children: [ + MihButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + submitForm(); + FocusScope.of(context) + .requestFocus(FocusNode()); + } else { + MihAlertServices() + .formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Calculate", + style: TextStyle( + color: MihColors.getPrimaryColor( MzansiInnovationHub.of(context)! .theme .mode == "Dark"), - width: 300, - child: Text( - "Calculate", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), + fontSize: 20, + fontWeight: FontWeight.bold, ), - MihButton( - onPressed: () { - clearInput(); - }, - buttonColor: MihColors.getRedColor( + ), + ), + MihButton( + onPressed: () { + clearInput(); + }, + buttonColor: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Clear", + style: TextStyle( + color: MihColors.getPrimaryColor( MzansiInnovationHub.of(context)! .theme .mode == "Dark"), - width: 300, - child: Text( - "Clear", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), + fontSize: 20, + fontWeight: FontWeight.bold, ), - ], + ), ), - ), - ], + ], + ), ), ], ), - ), - ); - } else { - return Center( - child: Text( - "Error pulling Currency Exchange Data.", - style: TextStyle( - fontSize: 25, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark")), - textAlign: TextAlign.center, - ), - ); - } - }); + ], + ), + ), + ); + }, + ); } } diff --git a/Frontend/lib/mih_packages/calculator/package_tools/tip_calc.dart b/Frontend/lib/mih_packages/calculator/package_tools/tip_calc.dart index f9269868..229dbd1e 100644 --- a/Frontend/lib/mih_packages/calculator/package_tools/tip_calc.dart +++ b/Frontend/lib/mih_packages/calculator/package_tools/tip_calc.dart @@ -1,5 +1,6 @@ import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_banner_ad.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; @@ -14,6 +15,7 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:math_expressions/math_expressions.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; +import 'package:provider/provider.dart'; class TipCalc extends StatefulWidget { const TipCalc({super.key}); @@ -30,7 +32,6 @@ class _TipCalcState extends State { final ValueNotifier splitValue = ValueNotifier(""); late bool splitPosition; final _formKey = GlobalKey(); - MihBannerAd _bannerAd = MihBannerAd(); String tip = ""; String total = ""; String amountPerPerson = ""; @@ -98,9 +99,7 @@ class _TipCalcState extends State { fullscreen: false, windowTitle: "Calculation Results", onWindowTapClose: () { - setState(() { - _bannerAd = MihBannerAd(); - }); + context.read().loadBannerAd(); Navigator.pop(context); }, windowBody: Column( @@ -231,7 +230,9 @@ class _TipCalcState extends State { ), ), SizedBox(height: 10), - SizedBox(child: _bannerAd), + Consumer(builder: (context, bannerAdDisplay, child) { + return MihBannerAd(); + }), // if (splitBillController.text == "Yes") const Divider(), ], ), diff --git a/Frontend/lib/mih_packages/calendar/builder/build_appointment_list.dart b/Frontend/lib/mih_packages/calendar/builder/build_appointment_list.dart index b195fb75..d56ef908 100644 --- a/Frontend/lib/mih_packages/calendar/builder/build_appointment_list.dart +++ b/Frontend/lib/mih_packages/calendar/builder/build_appointment_list.dart @@ -2,8 +2,11 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:go_router/go_router.dart'; import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/appointment.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_calendar_services.dart'; @@ -17,18 +20,10 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/appointment.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class BuildAppointmentList extends StatefulWidget { - final List appointmentList; - final AppUser signedInUser; - final Business? business; - final BusinessUser? businessUser; - final bool personalSelected; final bool inWaitingRoom; final TextEditingController titleController; final TextEditingController descriptionIDController; @@ -38,11 +33,6 @@ class BuildAppointmentList extends StatefulWidget { const BuildAppointmentList({ super.key, - required this.appointmentList, - required this.signedInUser, - required this.business, - required this.businessUser, - required this.personalSelected, required this.inWaitingRoom, required this.titleController, required this.descriptionIDController, @@ -77,22 +67,39 @@ class _BuildAppointmentListState extends State { } } - Widget displayAppointment(int index, double bodyWidth) { - String heading = - "${widget.appointmentList[index].date_time.split('T')[1].substring(0, 5)} - ${widget.appointmentList[index].title.toUpperCase()}"; - String description = widget.appointmentList[index].description; - DateTime now = new DateTime.now(); - int hourNow = int.parse(now.toString().split(' ')[1].substring(0, 2)); - String date = - new DateTime(now.year, now.month, now.day).toString().split(' ')[0]; - String appointDate = widget.appointmentList[index].date_time.split('T')[0]; - int appointHour = int.parse( - widget.appointmentList[index].date_time.split('T')[1].substring(0, 2)); - // print("Date Time Now: $now"); - // print("Hour Now: $hourNow"); - // print("Date: $date"); - // print("Appointment Date: $appointDate"); - // print("Appointment Hour: $appointHour"); + Widget displayAppointment(MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, int index, double bodyWidth) { + List appointmentList = mzansiProfileProvider.personalHome + ? mihCalendarProvider.personalAppointments! + : mihCalendarProvider.businessAppointments!; + String heading = ""; + String description = ""; + DateTime now; + int hourNow = 0; + String date = ""; + int appointHour = 0; + String appointDate = ""; + if (appointmentList[index].date_time.contains("T")) { + heading = + "${appointmentList[index].date_time.split('T')[1].substring(0, 5)} - ${appointmentList[index].title.toUpperCase()}"; + description = appointmentList[index].description; + now = DateTime.now(); + hourNow = int.parse(now.toString().split(' ')[1].substring(0, 2)); + date = DateTime(now.year, now.month, now.day).toString().split(' ')[0]; + appointDate = appointmentList[index].date_time.split('T')[0]; + appointHour = int.parse( + appointmentList[index].date_time.split('T')[1].substring(0, 2)); + } else { + heading = + "${appointmentList[index].date_time.split(' ')[1].substring(0, 5)} - ${appointmentList[index].title.toUpperCase()}"; + description = appointmentList[index].description; + now = DateTime.now(); + hourNow = int.parse(now.toString().split(' ')[1].substring(0, 2)); + date = DateTime(now.year, now.month, now.day).toString().split(' ')[0]; + appointDate = appointmentList[index].date_time.split(' ')[0]; + appointHour = int.parse( + appointmentList[index].date_time.split(' ')[1].substring(0, 2)); + } Color appointmentColor = MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"); if (date == appointDate) { @@ -132,26 +139,28 @@ class _BuildAppointmentListState extends State { ), onTap: () { setState(() { - widget.titleController.text = widget.appointmentList[index].title; + widget.titleController.text = appointmentList[index].title; widget.descriptionIDController.text = - widget.appointmentList[index].description; + appointmentList[index].description; widget.dateController.text = - widget.appointmentList[index].date_time.split('T')[0]; - widget.timeController.text = widget.appointmentList[index].date_time - .split('T')[1] - .substring(0, 5); + appointmentList[index].date_time.split('T')[0]; + widget.timeController.text = + appointmentList[index].date_time.split('T')[1].substring(0, 5); }); if (widget.inWaitingRoom == false) { - appointmentDetailsWindow(index, bodyWidth); + appointmentDetailsWindow( + mzansiProfileProvider, mihCalendarProvider, index, bodyWidth); } else { - waitingRiinAppointmentDetailsWindow(index, bodyWidth); + waitingRoomAppointmentDetailsWindow( + mzansiProfileProvider, mihCalendarProvider, index, bodyWidth); } }, ), ); } - void appointmentDetailsWindow(int index, double bodyWidth) { + void appointmentDetailsWindow(MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, int index, double bodyWidth) { showDialog( context: context, barrierDismissible: false, @@ -177,7 +186,8 @@ class _BuildAppointmentListState extends State { backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - appointmentUpdateWindow(index, bodyWidth); + appointmentUpdateWindow(mzansiProfileProvider, + mihCalendarProvider, index, bodyWidth); }, ), SpeedDialChild( @@ -197,7 +207,8 @@ class _BuildAppointmentListState extends State { backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - deleteAppointmentConfirmationWindow(index); + deleteAppointmentConfirmationWindow( + mzansiProfileProvider, mihCalendarProvider, index); }, ), ], @@ -273,7 +284,11 @@ class _BuildAppointmentListState extends State { ); } - void waitingRiinAppointmentDetailsWindow(int index, double bodyWidth) { + void waitingRoomAppointmentDetailsWindow( + MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, + int index, + double bodyWidth) { showDialog( context: context, barrierDismissible: false, @@ -299,7 +314,8 @@ class _BuildAppointmentListState extends State { backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - appointmentUpdateWindow(index, bodyWidth); + appointmentUpdateWindow(mzansiProfileProvider, + mihCalendarProvider, index, bodyWidth); }, ), SpeedDialChild( @@ -319,7 +335,8 @@ class _BuildAppointmentListState extends State { backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - deleteAppointmentConfirmationWindow(index); + deleteAppointmentConfirmationWindow( + mzansiProfileProvider, mihCalendarProvider, index); }, ), ], @@ -405,7 +422,11 @@ class _BuildAppointmentListState extends State { ); } - void appointmentUpdateWindow(int index, double bodyWidth) { + void appointmentUpdateWindow(MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, int index, double bodyWidth) { + List appointmentList = mzansiProfileProvider.personalHome + ? mihCalendarProvider.personalAppointments! + : mihCalendarProvider.businessAppointments!; showDialog( context: context, barrierDismissible: false, @@ -415,13 +436,13 @@ class _BuildAppointmentListState extends State { windowTitle: "Update Appointment", onWindowTapClose: () { setState(() { - widget.titleController.text = widget.appointmentList[index].title; + widget.titleController.text = appointmentList[index].title; widget.descriptionIDController.text = - widget.appointmentList[index].description; + appointmentList[index].description; widget.dateController.text = - widget.appointmentList[index].date_time.split('T')[0]; - widget.timeController.text = widget - .appointmentList[index].date_time + appointmentList[index].date_time.split('T')[0]; + widget.timeController.text = appointmentList[index] + .date_time .split('T')[1] .substring(0, 5); }); @@ -497,7 +518,8 @@ class _BuildAppointmentListState extends State { MihButton( onPressed: () { if (_formKey.currentState!.validate()) { - updateAppointmentCall(index); + updateAppointmentCall(mzansiProfileProvider, + mihCalendarProvider, index); } else { MihAlertServices() .formNotFilledCompletely(context); @@ -542,7 +564,10 @@ class _BuildAppointmentListState extends State { } } - void deleteAppointmentConfirmationWindow(int index) { + void deleteAppointmentConfirmationWindow( + MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, + int index) { showDialog( context: context, barrierDismissible: false, @@ -550,46 +575,55 @@ class _BuildAppointmentListState extends State { return MIHDeleteMessage( deleteType: "Appointment", onTap: () { - deleteAppointmentCall(index); + deleteAppointmentCall( + mzansiProfileProvider, mihCalendarProvider, index); }); }, ); } - Future updateAppointmentCall(int index) async { + Future updateAppointmentCall( + MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, + int index) async { int statusCode; if (isAppointmentInputValid()) { - if (widget.personalSelected == true) { + List appointmentList = mzansiProfileProvider.personalHome + ? mihCalendarProvider.personalAppointments! + : mihCalendarProvider.businessAppointments!; + if (mzansiProfileProvider.personalHome == true) { statusCode = await MihMzansiCalendarApis.updatePersonalAppointment( - widget.signedInUser, - widget.business, + mzansiProfileProvider.user!, + mzansiProfileProvider.business, null, - widget.appointmentList[index].idappointments, + appointmentList[index].idappointments, widget.titleController.text, widget.descriptionIDController.text, widget.dateController.text, widget.timeController.text, + mihCalendarProvider, context, ); - } else if (widget.personalSelected == false && + } else if (mzansiProfileProvider.personalHome == false && widget.inWaitingRoom == false) { statusCode = await MihMzansiCalendarApis.updateBusinessAppointment( - widget.signedInUser, - widget.business, - widget.businessUser, - widget.appointmentList[index].idappointments, + mzansiProfileProvider.user!, + mzansiProfileProvider.business, + mzansiProfileProvider.businessUser, + appointmentList[index].idappointments, widget.titleController.text, widget.descriptionIDController.text, widget.dateController.text, widget.timeController.text, + mihCalendarProvider, context, ); } else { statusCode = await MihMzansiCalendarApis.updatePatientAppointment( - widget.signedInUser, - widget.business, - widget.businessUser, - widget.appointmentList[index].idappointments, + mzansiProfileProvider.user!, + mzansiProfileProvider.business, + mzansiProfileProvider.businessUser, + appointmentList[index].idappointments, widget.titleController.text, widget.descriptionIDController.text, widget.dateController.text, @@ -604,27 +638,20 @@ class _BuildAppointmentListState extends State { KenLogger.warning("calendar route"); context.goNamed( "mihCalendar", - extra: CalendarArguments( - widget.signedInUser, - widget.personalSelected, - widget.business, - widget.businessUser, - ), ); } else { KenLogger.warning("waiting room route"); // GoRouter.of(context).refresh(); context.goNamed( 'mihHome', - extra: false, ); context.goNamed( 'patientManager', extra: PatManagerArguments( - widget.signedInUser, + mzansiProfileProvider.user!, false, - widget.business, - widget.businessUser, + mzansiProfileProvider.business, + mzansiProfileProvider.businessUser, ), ); // context.pop(); @@ -642,22 +669,26 @@ class _BuildAppointmentListState extends State { } } - Future deleteAppointmentCall(int index) async { + Future deleteAppointmentCall( + MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, + int index) async { + List appointmentList = mzansiProfileProvider.personalHome + ? mihCalendarProvider.personalAppointments! + : mihCalendarProvider.businessAppointments!; int statucCode = await MihMzansiCalendarApis.deleteAppointmentAPICall( - widget.signedInUser, - widget.personalSelected, - widget.business, - widget.businessUser, + mzansiProfileProvider.user!, + mzansiProfileProvider.personalHome, + mzansiProfileProvider.business, + mzansiProfileProvider.businessUser, widget.inWaitingRoom, - widget.appointmentList[index].idappointments, + appointmentList[index].idappointments, + mihCalendarProvider, context, ); if (statucCode == 200) { context.pop(); context.pop(); - setState(() { - widget.appointmentList.removeAt(index); - }); successPopUp("Successfully Deleted Appointment", "You appointment has been successfully deleted from your calendar."); } else { @@ -730,20 +761,24 @@ class _BuildAppointmentListState extends State { ); } - bool canEditAppointment(int index) { - if (widget.personalSelected == true && - widget.appointmentList[index].app_id == widget.signedInUser.app_id && - widget.appointmentList[index].business_id == "") { + bool canEditAppointment(MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, int index) { + List appointmentList = mzansiProfileProvider.personalHome + ? mihCalendarProvider.personalAppointments! + : mihCalendarProvider.businessAppointments!; + if (mzansiProfileProvider.personalHome == true && + appointmentList[index].app_id == mzansiProfileProvider.user!.app_id && + appointmentList[index].business_id == "") { return true; - } else if (widget.personalSelected == false && - widget.appointmentList[index].business_id == - widget.business!.business_id && - widget.appointmentList[index].app_id.isEmpty) { + } else if (mzansiProfileProvider.personalHome == false && + appointmentList[index].business_id == + mzansiProfileProvider.business!.business_id && + appointmentList[index].app_id.isEmpty) { return true; - } else if (widget.personalSelected == false && - widget.appointmentList[index].business_id == - widget.business!.business_id && - widget.appointmentList[index].app_id.isNotEmpty) { + } else if (mzansiProfileProvider.personalHome == false && + appointmentList[index].business_id == + mzansiProfileProvider.business!.business_id && + appointmentList[index].app_id.isNotEmpty) { return true; } else { return false; @@ -765,16 +800,27 @@ class _BuildAppointmentListState extends State { width = size.width; height = size.height; }); - return Padding( - padding: EdgeInsets.symmetric(horizontal: getPaddingSize()), - child: ListView.builder( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: widget.appointmentList.length, - itemBuilder: (context, index) { - return displayAppointment(index, width); - }, - ), + return Consumer2( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, + Widget? child) { + List appointmentList = mzansiProfileProvider.personalHome + ? mihCalendarProvider.personalAppointments! + : mihCalendarProvider.businessAppointments!; + return Padding( + padding: EdgeInsets.symmetric(horizontal: getPaddingSize()), + child: ListView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: appointmentList.length, + itemBuilder: (context, index) { + return displayAppointment( + mzansiProfileProvider, mihCalendarProvider, index, width); + }, + ), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/calendar/mzansi_calendar.dart b/Frontend/lib/mih_packages/calendar/mzansi_calendar.dart index 2e5bbd51..45f093da 100644 --- a/Frontend/lib/mih_packages/calendar/mzansi_calendar.dart +++ b/Frontend/lib/mih_packages/calendar/mzansi_calendar.dart @@ -2,15 +2,15 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_packages/calendar/package_tools/appointments.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MzansiCalendar extends StatefulWidget { - final CalendarArguments arguments; const MzansiCalendar({ super.key, - required this.arguments, }); @override @@ -18,8 +18,6 @@ class MzansiCalendar extends StatefulWidget { } class _MzansiCalendarState extends State { - int _selcetedIndex = 0; - @override Widget build(BuildContext context) { return MihPackage( @@ -27,12 +25,9 @@ class _MzansiCalendarState extends State { appTools: getTools(), appBody: getToolBody(), appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); - print("Index: $_selcetedIndex"); + selectedbodyIndex: context.watch().toolIndex, + onIndexChange: (newIndex) { + context.read().setToolIndex(newIndex); }, ); } @@ -42,10 +37,9 @@ class _MzansiCalendarState extends State { icon: const Icon(Icons.arrow_back), iconSize: 35, onTap: () { - // Navigator.of(context).pop(); + context.read().resetSelectedDay(); context.goNamed( 'mihHome', - extra: widget.arguments.personalSelected, ); FocusScope.of(context).unfocus(); }, @@ -55,33 +49,28 @@ class _MzansiCalendarState extends State { MihPackageTools getTools() { Map temp = {}; temp[const Icon(Icons.calendar_month)] = () { - setState(() { - _selcetedIndex = 0; - }); + context.read().setToolIndex(0); }; return MihPackageTools( tools: temp, - selcetedIndex: _selcetedIndex, + selcetedIndex: context.watch().toolIndex, ); } List getToolBody() { List toolBodies = [ //appointment here - Appointments( - signedInUser: widget.arguments.signedInUser, - business: widget.arguments.business, - businessUser: widget.arguments.businessUser, - personalSelected: widget.arguments.personalSelected, - ), + Appointments(), ]; return toolBodies; } List getToolTitle() { + MzansiProfileProvider mzansiProfileProvider = + context.read(); List toolTitles = [ - widget.arguments.personalSelected == true ? "Personal" : "Business", + mzansiProfileProvider.personalHome == true ? "Personal" : "Business", ]; return toolTitles; } diff --git a/Frontend/lib/mih_packages/calendar/package_tiles/mzansi_calendar_tile.dart b/Frontend/lib/mih_packages/calendar/package_tiles/mzansi_calendar_tile.dart index 7abb6097..545aac53 100644 --- a/Frontend/lib/mih_packages/calendar/package_tiles/mzansi_calendar_tile.dart +++ b/Frontend/lib/mih_packages/calendar/package_tiles/mzansi_calendar_tile.dart @@ -2,17 +2,14 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; class MzansiCalendarTile extends StatefulWidget { - final CalendarArguments arguments; final double packageSize; const MzansiCalendarTile({ super.key, - required this.arguments, required this.packageSize, }); @@ -27,7 +24,6 @@ class _MzansiCalendarTileState extends State { onTap: () { context.goNamed( "mihCalendar", - extra: widget.arguments, ); // Navigator.of(context).pushNamed( // '/calendar', diff --git a/Frontend/lib/mih_packages/calendar/package_tools/appointments.dart b/Frontend/lib/mih_packages/calendar/package_tools/appointments.dart index db9bb941..1d198a82 100644 --- a/Frontend/lib/mih_packages/calendar/package_tools/appointments.dart +++ b/Frontend/lib/mih_packages/calendar/package_tools/appointments.dart @@ -1,7 +1,13 @@ +import 'package:flutter/material.dart'; import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_calendar.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_calendar_services.dart'; @@ -17,29 +23,12 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_time_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/appointment.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; import 'package:mzansi_innovation_hub/mih_packages/calendar/builder/build_appointment_list.dart'; -import 'package:flutter/material.dart'; -import '../../../main.dart'; - -import '../../../mih_components/mih_package_components/mih_calendar.dart'; -import '../../../mih_components/mih_pop_up_messages/mih_loading_circle.dart'; -import '../../../mih_config/mih_env.dart'; -import '../../../mih_components/mih_objects/app_user.dart'; +import 'package:provider/provider.dart'; class Appointments extends StatefulWidget { - final AppUser signedInUser; - final Business? business; - final BusinessUser? businessUser; - final bool personalSelected; - const Appointments({ super.key, - required this.signedInUser, - required this.business, - required this.businessUser, - required this.personalSelected, }); @override @@ -57,25 +46,18 @@ class _PatientAccessRequestState extends State { TextEditingController(); final TextEditingController _appointmentTimeController = TextEditingController(); - String baseUrl = AppEnviroment.baseApiUrl; - - String selectedDay = DateTime.now().toString().split(" ")[0]; - - late Future> personalAppointmentResults; - late Future> businessAppointmentResults; - late Future> appointmentResults; + bool isLoading = true; final _formKey = GlobalKey(); - Widget displayAppointmentList(List appointmentList) { + Widget displayAppointmentList(MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider) { + List appointmentList = mzansiProfileProvider.personalHome + ? mihCalendarProvider.personalAppointments! + : mihCalendarProvider.businessAppointments!; if (appointmentList.isNotEmpty) { return Expanded( child: BuildAppointmentList( - appointmentList: appointmentList, - signedInUser: widget.signedInUser, - business: widget.business, - businessUser: widget.businessUser, - personalSelected: widget.personalSelected, inWaitingRoom: false, titleController: _appointmentTitleController, descriptionIDController: _appointmentDescriptionIDController, @@ -101,7 +83,7 @@ class _PatientAccessRequestState extends State { ), const SizedBox(height: 10), Text( - "No appointments for $selectedDay", + "No appointments for ${mihCalendarProvider.selectedDay}", textAlign: TextAlign.center, overflow: TextOverflow.visible, style: TextStyle( @@ -147,7 +129,8 @@ class _PatientAccessRequestState extends State { ); } - void addAppointmentWindow(double width) { + void addAppointmentWindow(MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, double width) { showDialog( context: context, barrierDismissible: false, @@ -227,7 +210,8 @@ class _PatientAccessRequestState extends State { child: MihButton( onPressed: () { if (_formKey.currentState!.validate()) { - addAppointmentCall(); + addAppointmentCall( + mzansiProfileProvider, mihCalendarProvider); } else { MihAlertServices().formNotFilledCompletely(context); } @@ -269,28 +253,33 @@ class _PatientAccessRequestState extends State { } } - Future addAppointmentCall() async { + Future addAppointmentCall( + MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, + ) async { if (isAppointmentInputValid()) { int statusCode; - if (widget.personalSelected == false) { + if (mzansiProfileProvider.personalHome == false) { statusCode = await MihMzansiCalendarApis.addBusinessAppointment( - widget.signedInUser, - widget.business!, - widget.businessUser!, + mzansiProfileProvider.user!, + mzansiProfileProvider.business!, + mzansiProfileProvider.businessUser!, false, _appointmentTitleController.text, _appointmentDescriptionIDController.text, _appointmentDateController.text, _appointmentTimeController.text, + mihCalendarProvider, context, ); } else { statusCode = await MihMzansiCalendarApis.addPersonalAppointment( - widget.signedInUser, + mzansiProfileProvider.user!, _appointmentTitleController.text, _appointmentDescriptionIDController.text, _appointmentDateController.text, _appointmentTimeController.text, + mihCalendarProvider, context, ); } @@ -298,20 +287,20 @@ class _PatientAccessRequestState extends State { context.pop(); successPopUp("Successfully Added Appointment", "You appointment has been successfully added to your calendar."); - setState(() { - if (widget.personalSelected) { - appointmentResults = MihMzansiCalendarApis.getPersonalAppointments( - widget.signedInUser.app_id, - selectedDay, - ); - } else { - appointmentResults = MihMzansiCalendarApis.getBusinessAppointments( - widget.business!.business_id, - false, - selectedDay, - ); - } - }); + if (mzansiProfileProvider.personalHome == true) { + await MihMzansiCalendarApis.getPersonalAppointments( + mzansiProfileProvider.user!.app_id, + mihCalendarProvider.selectedDay, + mihCalendarProvider, + ); + } else { + await MihMzansiCalendarApis.getBusinessAppointments( + mzansiProfileProvider.business!.business_id, + false, + mihCalendarProvider.selectedDay, + mihCalendarProvider, + ); + } } else { internetConnectionPopUp(); } @@ -397,8 +386,8 @@ class _PatientAccessRequestState extends State { ); } - String getTitle() { - if (widget.personalSelected == false) { + String getTitle(MzansiProfileProvider mzansiProfileProvider) { + if (mzansiProfileProvider.personalHome == false) { return "Business Appointments"; } else { return "Personal Appointments"; @@ -407,108 +396,114 @@ class _PatientAccessRequestState extends State { void checkforchange() { setState(() { - if (widget.personalSelected == false) { - appointmentResults = MihMzansiCalendarApis.getBusinessAppointments( - widget.business!.business_id, - false, - selectedDay, - ); - } else { - appointmentResults = MihMzansiCalendarApis.getPersonalAppointments( - widget.signedInUser.app_id, - selectedDay, - ); - } + isLoading = true; }); + _loadInitialAppointments(); } Widget getBody(double width) { - return Stack( - children: [ - MihSingleChildScroll( - child: Column( - children: [ - MIHCalendar( - calendarWidth: 500, - rowHeight: 35, - setDate: (value) { - setState(() { - selectedDay = value; - selectedAppointmentDateController.text = selectedDay; - }); - }), - // Divider( - // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - Row( - mainAxisSize: MainAxisSize.max, + if (isLoading) { + return const Center( + child: Mihloadingcircle(), + ); + } + return Consumer2( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, + MihCalendarProvider mihCalendarProvider, + Widget? child) { + return Stack( + children: [ + MihSingleChildScroll( + child: Column( children: [ - FutureBuilder( - future: appointmentResults, - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState.waiting) { - return const Expanded( - child: Center(child: Mihloadingcircle())); - } else if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - return displayAppointmentList(snapshot.requireData); - } else { - return Center( - child: Text( - "Error pulling appointments", - style: TextStyle( - fontSize: 25, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark")), - textAlign: TextAlign.center, - ), - ); - } + MIHCalendar( + calendarWidth: 500, + rowHeight: 35, + setDate: (value) { + mihCalendarProvider.setSelectedDay(value); + setState(() { + selectedAppointmentDateController.text = value; + }); }), + // Divider( + // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + displayAppointmentList( + mzansiProfileProvider, + mihCalendarProvider, + ), + ], + ) ], - ) - ], - ), - ), - Positioned( - right: 10, - bottom: 10, - child: MihFloatingMenu( - icon: Icons.add, - animatedIcon: AnimatedIcons.menu_close, - children: [ - SpeedDialChild( - child: Icon( - Icons.add, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - label: "Add Appointment", - labelBackgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - labelStyle: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontWeight: FontWeight.bold, - ), - backgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onTap: () { - addAppointmentWindow(width); - }, - ) - ], - ), - ), - ], + ), + ), + Positioned( + right: 10, + bottom: 10, + child: MihFloatingMenu( + icon: Icons.add, + animatedIcon: AnimatedIcons.menu_close, + children: [ + SpeedDialChild( + child: Icon( + Icons.add, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + label: "Add Appointment", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onTap: () { + addAppointmentWindow( + mzansiProfileProvider, mihCalendarProvider, width); + }, + ) + ], + ), + ), + ], + ); + }, ); } + Future _loadInitialAppointments() async { + MzansiProfileProvider mzansiProfileProvider = + context.read(); + MihCalendarProvider mihCalendarProvider = + context.read(); + if (mzansiProfileProvider.personalHome == false) { + await MihMzansiCalendarApis.getBusinessAppointments( + mzansiProfileProvider.business!.business_id, + false, + mihCalendarProvider.selectedDay, + mihCalendarProvider, + ); + } else { + await MihMzansiCalendarApis.getPersonalAppointments( + mzansiProfileProvider.user!.app_id, + mihCalendarProvider.selectedDay, + mihCalendarProvider, + ); + } + setState(() { + isLoading = false; + }); + } + @override void dispose() { selectedAppointmentDateController.dispose(); @@ -522,19 +517,8 @@ class _PatientAccessRequestState extends State { @override void initState() { selectedAppointmentDateController.addListener(checkforchange); - setState(() { - if (widget.personalSelected == false) { - appointmentResults = MihMzansiCalendarApis.getBusinessAppointments( - widget.business!.business_id, - false, - selectedDay, - ); - } else { - appointmentResults = MihMzansiCalendarApis.getPersonalAppointments( - widget.signedInUser.app_id, - selectedDay, - ); - } + WidgetsBinding.instance.addPostFrameCallback((_) async { + _loadInitialAppointments(); }); super.initState(); } diff --git a/Frontend/lib/mih_packages/mih_authentication/mih_authentication.dart b/Frontend/lib/mih_packages/mih_authentication/mih_authentication.dart index b255f91d..3511ed90 100644 --- a/Frontend/lib/mih_packages/mih_authentication/mih_authentication.dart +++ b/Frontend/lib/mih_packages/mih_authentication/mih_authentication.dart @@ -4,8 +4,10 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_authentication_provider.dart'; import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/package_tools/mih_register.dart'; import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/package_tools/mih_sign_in.dart'; +import 'package:provider/provider.dart'; class MihAuthentication extends StatefulWidget { const MihAuthentication({super.key}); @@ -15,56 +17,35 @@ class MihAuthentication extends StatefulWidget { } class _MihAuthenticationState extends State { - int _selcetedIndex = 0; - @override Widget build(BuildContext context) { return MihPackage( appActionButton: getAction(), appTools: getTools(), appBody: getToolBody(), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); + selectedbodyIndex: context.watch().toolIndex, + onIndexChange: (newIndex) { + context.read().setToolIndex(newIndex); }, ); } List getToolBody() { - List toolBodies = [ - MihSignIn( - onNewUserButtonTap: () { - setState(() { - _selcetedIndex = 1; - }); - }, - ), - MihRegister(onExistingUserButtonTap: () { - setState(() { - _selcetedIndex = 0; - }); - }) - ]; + List toolBodies = [MihSignIn(), MihRegister()]; return toolBodies; } MihPackageTools getTools() { Map temp = {}; temp[const Icon(Icons.perm_identity)] = () { - setState(() { - _selcetedIndex = 0; - }); + context.read().setToolIndex(0); }; temp[const Icon(Icons.create)] = () { - setState(() { - _selcetedIndex = 1; - }); + context.read().setToolIndex(1); }; return MihPackageTools( tools: temp, - selcetedIndex: _selcetedIndex, + selcetedIndex: context.watch().toolIndex, ); } @@ -75,7 +56,7 @@ class _MihAuthenticationState extends State { icon: const Icon(MihIcons.mihLogo), iconSize: 45, onTap: () { - context.goNamed("aboutMih", extra: 0); + context.goNamed("aboutMih", extra: true); }, ), ); diff --git a/Frontend/lib/mih_packages/mih_authentication/package_tools/mih_register.dart b/Frontend/lib/mih_packages/mih_authentication/package_tools/mih_register.dart index 6fc9e0de..f16c6ef0 100644 --- a/Frontend/lib/mih_packages/mih_authentication/package_tools/mih_register.dart +++ b/Frontend/lib/mih_packages/mih_authentication/package_tools/mih_register.dart @@ -11,19 +11,20 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; 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_providers/mih_authentication_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; import 'package:supertokens_flutter/http.dart' as http; import 'package:supertokens_flutter/supertokens.dart'; class MihRegister extends StatefulWidget { - final void Function()? onExistingUserButtonTap; const MihRegister({ super.key, - required this.onExistingUserButtonTap, }); @override @@ -75,6 +76,7 @@ class _MihRegisterState extends State { } Future signUserUp() async { + context.read().reset(); if (!validEmail()) { emailError(); } else if (passwordController.text != confirmPasswordController.text) { @@ -366,7 +368,11 @@ class _MihRegisterState extends State { ), ), MihButton( - onPressed: widget.onExistingUserButtonTap, + onPressed: () { + context + .read() + .setToolIndex(0); + }, buttonColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), diff --git a/Frontend/lib/mih_packages/mih_authentication/package_tools/mih_sign_in.dart b/Frontend/lib/mih_packages/mih_authentication/package_tools/mih_sign_in.dart index c6bb47f2..68751125 100644 --- a/Frontend/lib/mih_packages/mih_authentication/package_tools/mih_sign_in.dart +++ b/Frontend/lib/mih_packages/mih_authentication/package_tools/mih_sign_in.dart @@ -9,18 +9,19 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_authentication_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_authentication_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_install_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; class MihSignIn extends StatefulWidget { - final void Function()? onNewUserButtonTap; const MihSignIn({ super.key, - required this.onNewUserButtonTap, }); @override @@ -39,6 +40,7 @@ class _MihSignInState extends State { //sign user in Future signUserIn() async { + context.read().reset(); try { successfulSignIn = await MihAuthenticationServices().signUserIn( emailController.text, @@ -381,7 +383,11 @@ class _MihSignInState extends State { ), ), MihButton( - onPressed: widget.onNewUserButtonTap, + onPressed: () { + context + .read() + .setToolIndex(1); + }, buttonColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), diff --git a/Frontend/lib/mih_packages/mih_home/components/mih_app_drawer.dart b/Frontend/lib/mih_packages/mih_home/components/mih_app_drawer.dart index ad15cbef..6a0e9f27 100644 --- a/Frontend/lib/mih_packages/mih_home/components/mih_app_drawer.dart +++ b/Frontend/lib/mih_packages/mih_home/components/mih_app_drawer.dart @@ -1,21 +1,27 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/about_mih_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_authentication_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calculator_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_wallet_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:provider/provider.dart'; import '../../../main.dart'; import 'package:supertokens_flutter/supertokens.dart'; class MIHAppDrawer extends StatefulWidget { - final AppUser signedInUser; - final ImageProvider? propicFile; - const MIHAppDrawer({ super.key, - required this.signedInUser, - required this.propicFile, }); @override @@ -25,6 +31,21 @@ class MIHAppDrawer extends StatefulWidget { class _MIHAppDrawerState extends State { final proPicController = TextEditingController(); late Widget profilePictureLoaded; + + void resetProviders() { + context.read().reset(); + context.read().reset(); + context.read().reset(); + context.read().reset(); + context.read().reset(); + context.read().reset(); + context.read().reset(); + context.read().reset(); + context.read().reset(); + context.read().reset(); + context.read().reset(); + } + Future signOut() async { await SuperTokens.signOut(completionHandler: (error) { // handle error if any @@ -32,19 +53,30 @@ class _MIHAppDrawerState extends State { return true; } - Widget displayProPic() { + Widget displayProPic(MzansiProfileProvider mzansiProfileProvider) { return GestureDetector( onTap: () { - context.goNamed( - 'mzansiProfileManage', - extra: AppProfileUpdateArguments( - widget.signedInUser, - widget.propicFile, - ), - ); + if (mzansiProfileProvider.personalHome) { + context.goNamed( + 'mzansiProfileManage', + ); + } else { + if (mzansiProfileProvider.business == null) { + context.goNamed( + 'businessProfileSetup', + extra: mzansiProfileProvider.user, + ); + } else { + context.goNamed( + "businessProfileManage", + ); + } + } }, child: MihCircleAvatar( - imageFile: widget.propicFile, + imageFile: mzansiProfileProvider.personalHome + ? mzansiProfileProvider.userProfilePicture + : mzansiProfileProvider.businessProfilePicture, width: 60, editable: false, fileNameController: proPicController, @@ -66,9 +98,6 @@ class _MIHAppDrawerState extends State { @override void initState() { - setState(() { - profilePictureLoaded = displayProPic(); - }); super.initState(); } @@ -76,287 +105,329 @@ class _MIHAppDrawerState extends State { Widget build(BuildContext context) { // precacheImage( // MzansiInnovationHub.of(context)!.theme.logoImage().image, context); - return SafeArea( - child: Drawer( - //backgroundColor: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - child: LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - return Stack( - //fit: StackFit.passthrough, - children: [ - Column( - // reverse: false, - // padding: EdgeInsets.zero, - mainAxisSize: MainAxisSize.max, + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return SafeArea( + child: Drawer( + //backgroundColor: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + child: LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return Stack( + //fit: StackFit.passthrough, children: [ - DrawerHeader( - decoration: BoxDecoration( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - child: SizedBox( - height: 400, - width: constraints.maxWidth, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.max, - children: [ - profilePictureLoaded, - Text( - "${widget.signedInUser.fname} ${widget.signedInUser.lname}", - style: TextStyle( - fontWeight: FontWeight.bold, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - ), + Column( + // reverse: false, + // padding: EdgeInsets.zero, + mainAxisSize: MainAxisSize.max, + children: [ + DrawerHeader( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + child: SizedBox( + // height: 300, + width: constraints.maxWidth, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + children: [ + displayProPic(mzansiProfileProvider), + Visibility( + visible: !mzansiProfileProvider.personalHome, + child: Text( + mzansiProfileProvider.business?.Name ?? + "Setup Business", + style: TextStyle( + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ), + Visibility( + visible: mzansiProfileProvider.personalHome, + child: Text( + "${mzansiProfileProvider.user!.fname} ${mzansiProfileProvider.user!.lname}", + style: TextStyle( + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ), + Visibility( + visible: !mzansiProfileProvider.personalHome, + child: Text( + mzansiProfileProvider.business?.type ?? "", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ), + Visibility( + visible: mzansiProfileProvider.personalHome, + child: Text( + "@${mzansiProfileProvider.user!.username}", + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ), + Text( + mzansiProfileProvider.user!.type + .toUpperCase(), + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ], ), - Text( - "@${widget.signedInUser.username}", - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), + ), + ), + // ListTile( + // title: Row( + // mainAxisSize: MainAxisSize.max, + // children: [ + // Icon( + // Icons.home_outlined, + // color: + // MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + // const SizedBox(width: 25.0), + // Text( + // "Home", + // style: TextStyle( + // //fontWeight: FontWeight.bold, + // color: MzansiInnovationHub.of(context)! + // .theme + // .secondaryColor(), + // ), + // ), + // ], + // ), + // onTap: () { + // Navigator.of(context) + // .pushNamedAndRemoveUntil('/', (route) => false); + // }, + // ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + ListTile( + title: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Icon( + Icons.policy, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + const SizedBox(width: 25.0), + Text( + "Privacy Policy", + style: TextStyle( + //fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ], + ), + onTap: () { + WidgetsBinding.instance + .addPostFrameCallback((_) async { + context + .read() + .setToolIndex(1); + }); + context.goNamed( + "aboutMih", + extra: true, + ); + }, ), - ), - Text( - widget.signedInUser.type.toUpperCase(), - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), + ListTile( + title: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Icon( + Icons.design_services_rounded, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + const SizedBox(width: 25.0), + Text( + "Terms of Service", + style: TextStyle( + //fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ], + ), + onTap: () { + WidgetsBinding.instance + .addPostFrameCallback((_) async { + context + .read() + .setToolIndex(2); + }); + context.goNamed( + "aboutMih", + extra: true, + ); + }, ), - ), - ], + ListTile( + title: Row( + mainAxisSize: MainAxisSize.max, + children: [ + Icon( + Icons.logout, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + const SizedBox(width: 25.0), + Text( + "Sign Out", + style: TextStyle( + //fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ], + ), + onTap: () async { + await SuperTokens.signOut( + completionHandler: (error) { + print(error); + }); + if (await SuperTokens.doesSessionExist() == + false) { + resetProviders(); + await Future.delayed(Duration.zero); + if (context.mounted) { + context.goNamed( + 'mihHome', + ); + } + } + }, + ), + ], + ), + ), + ], + ), + Positioned( + top: 5, + right: 5, + width: 30, + height: 30, + child: InkWell( + onTap: () { + // setState(() { + // if (MzansiInnovationHub.of(context)?.theme.mode == + // "Dark") { + // //darkm = !darkm; + // MzansiInnovationHub.of(context)! + // .changeTheme(ThemeMode.light); + // //print("Dark Mode: $darkm"); + // } else { + // //darkm = !darkm; + // MzansiInnovationHub.of(context)! + // .changeTheme(ThemeMode.dark); + // //print("Dark Mode: $darkm"); + // } + // // Navigator.of(context).popAndPushNamed('/',); + // }); + context.goNamed("aboutMih"); + }, + child: Icon( + MihIcons.mihLogo, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), ), ), - ), - // ListTile( - // title: Row( - // mainAxisSize: MainAxisSize.max, - // children: [ - // Icon( - // Icons.home_outlined, - // color: - // MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // const SizedBox(width: 25.0), - // Text( - // "Home", - // style: TextStyle( - // //fontWeight: FontWeight.bold, - // color: MzansiInnovationHub.of(context)! - // .theme - // .secondaryColor(), - // ), - // ), - // ], - // ), - // onTap: () { - // Navigator.of(context) - // .pushNamedAndRemoveUntil('/', (route) => false); - // }, - // ), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.max, - children: [ - ListTile( - title: Row( - mainAxisSize: MainAxisSize.max, - children: [ - Icon( - Icons.policy, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - ), - const SizedBox(width: 25.0), - Text( - "Privacy Policy", - style: TextStyle( - //fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - ), - ), - ], - ), - onTap: () { - context.goNamed( - "aboutMih", - extra: AboutArguments( - true, - 1, - ), - ); - }, - ), - ListTile( - title: Row( - mainAxisSize: MainAxisSize.max, - children: [ - Icon( - Icons.design_services_rounded, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - ), - const SizedBox(width: 25.0), - Text( - "Terms of Service", - style: TextStyle( - //fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - ), - ), - ], - ), - onTap: () { - context.goNamed( - "aboutMih", - extra: AboutArguments( - true, - 2, - ), - ); - }, - ), - ListTile( - title: Row( - mainAxisSize: MainAxisSize.max, - children: [ - Icon( - Icons.logout, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - ), - const SizedBox(width: 25.0), - Text( - "Sign Out", - style: TextStyle( - //fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - ), - ), - ], - ), - onTap: () async { - await SuperTokens.signOut( - completionHandler: (error) { - print(error); - }); - if (await SuperTokens.doesSessionExist() == - false) { - context.goNamed( - 'mihHome', - extra: true, - ); - // Navigator.of(context).pop(); - // Navigator.of(context).popAndPushNamed( - // '/', - // arguments: AuthArguments(true, false), - // ); - } - }, - ), - ], - ), + // IconButton( + // onPressed: () { + // setState(() { + // if (MzansiInnovationHub.of(context)?.theme.mode == "Dark") { + // //darkm = !darkm; + // MzansiInnovationHub.of(context)!.changeTheme(ThemeMode.light); + // //print("Dark Mode: $darkm"); + // } else { + // //darkm = !darkm; + // MzansiInnovationHub.of(context)!.changeTheme(ThemeMode.dark); + // //print("Dark Mode: $darkm"); + // } + // Navigator.of(context).popAndPushNamed('/'); + // }); + // }, + // icon: Icon( + // Icons.light_mode, + // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // size: 35, + // ), + // ), ), ], - ), - Positioned( - top: 5, - right: 5, - width: 30, - height: 30, - child: InkWell( - onTap: () { - setState(() { - if (MzansiInnovationHub.of(context)?.theme.mode == - "Dark") { - //darkm = !darkm; - MzansiInnovationHub.of(context)! - .changeTheme(ThemeMode.light); - //print("Dark Mode: $darkm"); - } else { - //darkm = !darkm; - MzansiInnovationHub.of(context)! - .changeTheme(ThemeMode.dark); - //print("Dark Mode: $darkm"); - } - Navigator.of(context).pop(); - Navigator.of(context).popAndPushNamed( - '/', - arguments: AuthArguments(true, false), - ); - // Navigator.of(context).popAndPushNamed('/',); - }); - }, - child: Icon( - MihIcons.mihLogo, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - // IconButton( - // onPressed: () { - // setState(() { - // if (MzansiInnovationHub.of(context)?.theme.mode == "Dark") { - // //darkm = !darkm; - // MzansiInnovationHub.of(context)!.changeTheme(ThemeMode.light); - // //print("Dark Mode: $darkm"); - // } else { - // //darkm = !darkm; - // MzansiInnovationHub.of(context)!.changeTheme(ThemeMode.dark); - // //print("Dark Mode: $darkm"); - // } - // Navigator.of(context).popAndPushNamed('/'); - // }); - // }, - // icon: Icon( - // Icons.light_mode, - // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // size: 35, - // ), - // ), - ), - ], - ); - }, - ), - ), + ); + }, + ), + ), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mih_home/mih_home.dart b/Frontend/lib/mih_packages/mih_home/mih_home.dart index 1e90ccb0..877057e6 100644 --- a/Frontend/lib/mih_packages/mih_home/mih_home.dart +++ b/Frontend/lib/mih_packages/mih_home/mih_home.dart @@ -1,7 +1,8 @@ import 'package:go_router/go_router.dart'; import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/user_consent.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; @@ -13,22 +14,24 @@ import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_scack_bar.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/about_mih_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:mzansi_innovation_hub/mih_packages/mih_home/components/mih_app_drawer.dart'; -import 'package:mzansi_innovation_hub/mih_packages/mih_home/mih_home_error.dart'; import 'package:mzansi_innovation_hub/mih_packages/mih_home/package_tools/mih_business_home.dart'; import 'package:mzansi_innovation_hub/mih_packages/mih_home/package_tools/mih_personal_home.dart'; import 'package:flutter/material.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_service_calls.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_my_business_user_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_user_consent_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; +import 'package:provider/provider.dart'; -// ignore: must_be_immutable class MihHome extends StatefulWidget { - final bool personalSelected; const MihHome({ super.key, - required this.personalSelected, }); @override @@ -36,14 +39,77 @@ class MihHome extends StatefulWidget { } class _MihHomeState extends State { - final proPicController = TextEditingController(); - late int _selcetedIndex; - late bool _personalSelected; - late Future profileData; - late Future futureUserConsent; - bool showUserConsent = false; DateTime latestPrivacyPolicyDate = DateTime.parse("2024-12-01"); DateTime latestTermOfServiceDate = DateTime.parse("2024-12-01"); + bool _isLoadingInitialData = true; + + Future _loadInitialData() async { + if (mounted) { + setState(() { + _isLoadingInitialData = true; + }); + } + MzansiProfileProvider mzansiProfileProvider = + context.read(); + // Note: getUserData sets user and userProfilePicUrl in the provider + if (mzansiProfileProvider.user == null) { + await getUserData(); + } + // Note: getUserConsentStatus sets userConsent in the provider + if (mzansiProfileProvider.userConsent == null) { + await getUserConsentStatus(); + } + // 1. Get Business Data + if (mzansiProfileProvider.user != null && + mzansiProfileProvider.user!.type == "business" && + mzansiProfileProvider.business == null) { + KenLogger.success(mzansiProfileProvider.business == null + ? "Business is null, fetching business data..." + : "Business data already loaded."); + await getBusinessData(); + } + // 2. Set state after all data is loaded + if (mounted) { + setState(() { + _isLoadingInitialData = false; + }); + } + } + + Future getBusinessData() async { + AppUser? user = context.read().user; + String logoUrl; + String signatureUrl; + Business? responseBusiness = + await MihBusinessDetailsServices().getBusinessDetailsByUser(context); + // if (responseBusiness == null && user!.type == "business") { + // if (mounted) { + // context.goNamed( + // 'businessProfileSetup', + // extra: user, + // ); + // } + // } + + if (responseBusiness != null && user!.type == "business") { + // Get Business + // Business Profile Set Up aleary + logoUrl = await MihFileApi.getMinioFileUrl( + context.read().business!.logo_path, + context, + ); + context.read().setBusinessProfilePicUrl(logoUrl); + // Get Business User + await MihMyBusinessUserServices().getBusinessUser(context); + signatureUrl = await MihFileApi.getMinioFileUrl( + context.read().businessUser!.sig_path, + context, + ); + context + .read() + .setBusinessUserSignatureUrl(signatureUrl); + } + } bool showPolicyWindow(UserConsent? userConsent) { if (userConsent == null) { @@ -60,20 +126,19 @@ class _MihHomeState extends State { } } - void createOrUpdateAccpetance(UserConsent? userConsent, String app_id) { + void createOrUpdateAccpetance(MzansiProfileProvider mzansiProfileProvider) { + UserConsent? userConsent = mzansiProfileProvider.userConsent; userConsent != null ? MihUserConsentServices() .updateUserConsentStatus( - app_id, DateTime.now().toIso8601String(), DateTime.now().toIso8601String(), + mzansiProfileProvider, + context, ) .then((value) { if (value == 200) { - // setState(() { - // showUserConsent = false; - // }); - context.goNamed("mihHome", extra: false); + context.goNamed("mihHome"); ScaffoldMessenger.of(context).showSnackBar( MihSnackBar( child: Text("Thank you for accepting our Policies"), @@ -89,16 +154,14 @@ class _MihHomeState extends State { }) : MihUserConsentServices() .insertUserConsentStatus( - app_id, DateTime.now().toIso8601String(), DateTime.now().toIso8601String(), + mzansiProfileProvider, + context, ) .then((value) { if (value == 201) { - // setState(() { - // showUserConsent = false; - // }); - context.goNamed("mihHome", extra: false); + context.goNamed("mihHome"); ScaffoldMessenger.of(context).showSnackBar( MihSnackBar( child: Text("Thank you for accepting our Policies"), @@ -114,6 +177,25 @@ class _MihHomeState extends State { }); } + Future getUserData() async { + if (!mounted) return; + String url; + await MihUserServices().getUserDetails( + context, + ); + if (!mounted) return; + url = await MihFileApi.getMinioFileUrl( + context.read().user!.pro_pic_path, + context, + ); + context.read().setUserProfilePicUrl(url); + } + + Future getUserConsentStatus() async { + if (!mounted) return; + await MihUserConsentServices().getUserConsentStatus(context); + } + @override void dispose() { super.dispose(); @@ -122,19 +204,7 @@ class _MihHomeState extends State { @override void initState() { super.initState(); - profileData = MIHApiCalls().getProfile(10, context); - futureUserConsent = MihUserConsentServices().getUserConsentStatus(); - if (widget.personalSelected == true) { - setState(() { - _selcetedIndex = 0; - _personalSelected = true; - }); - } else { - setState(() { - _selcetedIndex = 1; - _personalSelected = false; - }); - } + _loadInitialData(); } List getToolTitle() { @@ -147,375 +217,339 @@ class _MihHomeState extends State { @override Widget build(BuildContext context) { - return FutureBuilder( - future: profileData, - builder: (context, asyncSnapshot) { - if (asyncSnapshot.connectionState == ConnectionState.waiting) { + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + if (_isLoadingInitialData) { return Scaffold( - body: const Mihloadingcircle( - // message: "Fetching your Data...", - ), + body: Center( + child: Mihloadingcircle(), + ), ); - } else if (asyncSnapshot.connectionState == ConnectionState.done && - asyncSnapshot.hasData) { - return Stack( - children: [ - MihPackage( - appActionButton: getAction(asyncSnapshot.data!.profilePicUrl), - appTools: getTools( - asyncSnapshot.data!.signedInUser.type != "personal"), - appBody: getToolBody(asyncSnapshot.data!), - appToolTitles: getToolTitle(), - actionDrawer: getActionDrawer( - asyncSnapshot.data!.signedInUser, - asyncSnapshot.data!.profilePicUrl, + } + // bool showConsentWindow = + // showPolicyWindow(mzansiProfileProvider.userConsent); + return Stack( + children: [ + RefreshIndicator( + onRefresh: () async { + await _loadInitialData(); + }, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: SizedBox( + height: MediaQuery.of(context).size.height, + child: MihPackage( + appActionButton: getAction(), + appTools: getTools(mzansiProfileProvider, + mzansiProfileProvider.user!.type != "personal"), + appBody: getToolBody(mzansiProfileProvider), + appToolTitles: getToolTitle(), + actionDrawer: getActionDrawer(), + selectedbodyIndex: + mzansiProfileProvider.personalHome ? 0 : 1, + onIndexChange: (newValue) { + mzansiProfileProvider.setPersonalHome(newValue == 0); + }, + ), ), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - if (_selcetedIndex == 0) { - setState(() { - _selcetedIndex = newValue; - _personalSelected = true; - }); - } else { - setState(() { - _selcetedIndex = newValue; - _personalSelected = false; - }); - } - }, ), - FutureBuilder( - future: futureUserConsent, - builder: (context, asyncSnapshotUserConsent) { - if (asyncSnapshotUserConsent.connectionState == - ConnectionState.waiting) { - showUserConsent = false; - } else if (asyncSnapshotUserConsent.connectionState == - ConnectionState.done && - asyncSnapshotUserConsent.hasData) { - showUserConsent = - showPolicyWindow(asyncSnapshotUserConsent.data); - } else if (asyncSnapshotUserConsent.connectionState == - ConnectionState.done && - !asyncSnapshotUserConsent.hasData) { - showUserConsent = true; - } else { - showUserConsent = false; - } - return Visibility( - visible: showUserConsent, - child: Container( - color: Colors.black.withValues(alpha: 0.5), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - children: [ - MihPackageWindow( - fullscreen: false, - windowTitle: - "Privacy Policy & Terms Of Service Alert!", - onWindowTapClose: () { - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.warning_amber_rounded, - size: 100, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark", - ), - ), - alertTitle: - "Oops, Looks like you missed a step!", - alertBody: Text( - "We're excited for you to keep using the MIH app! Before you do, please take a moment to accept our Privacy Policy and Terms of Service. Thanks for helping us keep your experience great!", - textAlign: TextAlign.center, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark", - ), - fontSize: 15, - fontWeight: FontWeight.normal, - ), - ), - alertColour: MihColors.getRedColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark", - ), - ); - }); - }, - windowBody: Column( - children: [ - Icon( - Icons.policy, - size: 150, + ), + Visibility( + visible: showPolicyWindow(mzansiProfileProvider.userConsent), + child: Container( + color: Colors.black.withValues(alpha: 0.5), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + MihPackageWindow( + fullscreen: false, + windowTitle: "Privacy Policy & Terms Of Service Alert!", + onWindowTapClose: () { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.warning_amber_rounded, + size: 100, + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark", + ), + ), + alertTitle: + "Oops, Looks like you missed a step!", + alertBody: Text( + "We're excited for you to keep using the MIH app! Before you do, please take a moment to accept our Privacy Policy and Terms of Service. Thanks for helping us keep your experience great!", + textAlign: TextAlign.center, + style: TextStyle( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)! .theme .mode == "Dark", ), + fontSize: 15, + fontWeight: FontWeight.normal, ), - const SizedBox(height: 10), - Text( - "Welcome to the MIH App", - textAlign: TextAlign.center, + ), + alertColour: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark", + ), + ); + }); + }, + windowBody: Column( + children: [ + Icon( + Icons.policy, + size: 150, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark", + ), + ), + const SizedBox(height: 10), + Text( + "Welcome to the MIH App", + textAlign: TextAlign.center, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark", + ), + fontSize: 30, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 10), + Text( + "To keep using the MIH app, please take a moment to review and accept our Policies. Our agreements helps us keep things running smoothly and securely.", + textAlign: TextAlign.center, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark", + ), + fontSize: 15, + fontWeight: FontWeight.normal, + ), + ), + const SizedBox(height: 20), + Center( + child: Wrap( + alignment: WrapAlignment.center, + spacing: 10, + runSpacing: 10, + children: [ + MihButton( + onPressed: () { + WidgetsBinding.instance + .addPostFrameCallback((_) async { + context + .read() + .setToolIndex(1); + }); + context.goNamed("aboutMih", + extra: + mzansiProfileProvider.personalHome); + }, + buttonColor: MihColors.getOrangeColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + elevation: 10, + width: 300, + child: Text( + "Privacy Policy", style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark", - ), - fontSize: 30, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + fontSize: 20, fontWeight: FontWeight.bold, ), ), - const SizedBox(height: 10), - Text( - "To keep using the MIH app, please take a moment to review and accept our Policies. Our agreements helps us keep things running smoothly and securely.", - textAlign: TextAlign.center, + ), + MihButton( + onPressed: () { + WidgetsBinding.instance + .addPostFrameCallback((_) async { + context + .read() + .setToolIndex(2); + }); + context.goNamed("aboutMih", + extra: + mzansiProfileProvider.personalHome); + }, + buttonColor: MihColors.getYellowColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + elevation: 10, + width: 300, + child: Text( + "Terms of Service", style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark", - ), - fontSize: 15, - fontWeight: FontWeight.normal, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, ), ), - const SizedBox(height: 20), - Center( - child: Wrap( - alignment: WrapAlignment.center, - spacing: 10, - runSpacing: 10, - children: [ - MihButton( - onPressed: () { - context.goNamed( - "aboutMih", - extra: AboutArguments( - widget.personalSelected, - 1, - ), - ); - }, - buttonColor: MihColors.getOrangeColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - elevation: 10, - width: 300, - child: Text( - "Privacy Policy", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of( - context)! - .theme - .mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - MihButton( - onPressed: () { - context.goNamed( - "aboutMih", - extra: AboutArguments( - widget.personalSelected, - 2, - ), - ); - }, - buttonColor: MihColors.getYellowColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - elevation: 10, - width: 300, - child: Text( - "Terms of Service", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of( - context)! - .theme - .mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - MihButton( - onPressed: () { - DateTime now = DateTime.now(); - KenLogger.success( - "Date Time Now: $now"); - createOrUpdateAccpetance( - asyncSnapshotUserConsent.data, - asyncSnapshot - .data!.signedInUser.app_id, - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - elevation: 10, - width: 300, - child: Text( - "Accept", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of( - context)! - .theme - .mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ], + ), + MihButton( + onPressed: () { + DateTime now = DateTime.now(); + KenLogger.success("Date Time Now: $now"); + createOrUpdateAccpetance( + mzansiProfileProvider); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + elevation: 10, + width: 300, + child: Text( + "Accept", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, ), ), - const SizedBox(height: 10), - ], - ), + ), + ], ), - ], - ), + ), + const SizedBox(height: 10), + ], ), - ); - }), - ], - ); - } else { - return MihHomeError( - errorMessage: asyncSnapshot.hasError - ? asyncSnapshot.error.toString() - : "An unknown error occurred", - ); - } + ), + ], + ), + ), + ), + ], + ); }, ); } - Widget getAction(String proPicUrl) { + Widget getAction() { return Builder(builder: (context) { - return MihPackageAction( - icon: Padding( - padding: const EdgeInsets.only(left: 5.0), - child: MihCircleAvatar( - imageFile: proPicUrl != "" ? NetworkImage(proPicUrl) : null, - width: 50, - editable: false, - fileNameController: proPicController, - userSelectedfile: null, - // frameColor: frameColor, - frameColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - backgroundColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onChange: (_) {}, - ), - // MIHProfilePicture( - // profilePictureFile: widget.propicFile, - // proPicController: proPicController, - // proPic: null, - // width: 45, - // radius: 21, - // drawerMode: false, - // editable: false, - // frameColor: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // onChange: (newProPic) {}, - // ), - ), - iconSize: 45, - onTap: () { - Scaffold.of(context).openDrawer(); - FocusScope.of(context) - .requestFocus(FocusNode()); // Fully unfocus all fields - // FocusScope.of(context).unfocus(); // Unfocus any text fields + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + ImageProvider? currentImage; + String imageKey; + if (mzansiProfileProvider.personalHome) { + currentImage = mzansiProfileProvider.userProfilePicture; + imageKey = 'user_${mzansiProfileProvider.userProfilePicUrl}'; + } else { + currentImage = mzansiProfileProvider.businessProfilePicture; + imageKey = + 'business_${mzansiProfileProvider.businessProfilePicUrl}'; + } + return MihPackageAction( + icon: Padding( + padding: const EdgeInsets.only(left: 5.0), + child: MihCircleAvatar( + key: Key(imageKey), + imageFile: currentImage, + width: 50, + editable: false, + fileNameController: null, + userSelectedfile: null, + // frameColor: frameColor, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onChange: (_) {}, + ), + ), + iconSize: 45, + onTap: () { + Scaffold.of(context).openDrawer(); + FocusScope.of(context) + .requestFocus(FocusNode()); // Fully unfocus all fields + // FocusScope.of(context).unfocus(); // Unfocus any text fields + }, + ); }, ); }); } - MIHAppDrawer getActionDrawer(AppUser signedInUser, String proPicUrl) { - return MIHAppDrawer( - signedInUser: signedInUser, - propicFile: proPicUrl != "" ? NetworkImage(proPicUrl) : null, - ); + MIHAppDrawer getActionDrawer() { + return MIHAppDrawer(); } - MihPackageTools getTools(bool isBusinessUser) { + MihPackageTools getTools( + MzansiProfileProvider mzansiProfileProvider, bool isBusinessUser) { Map temp = {}; temp[const Icon(Icons.person)] = () { setState(() { - _selcetedIndex = 0; - _personalSelected = true; + mzansiProfileProvider.setPersonalHome(true); }); }; if (isBusinessUser) { temp[const Icon(Icons.business_center)] = () { setState(() { - _selcetedIndex = 1; - _personalSelected = false; + mzansiProfileProvider.setPersonalHome(false); }); }; } return MihPackageTools( tools: temp, - selcetedIndex: _selcetedIndex, + selcetedIndex: mzansiProfileProvider.personalHome ? 0 : 1, ); } - List getToolBody(HomeArguments profData) { + List getToolBody(MzansiProfileProvider mzansiProfileProvider) { List toolBodies = []; + AppUser? user = mzansiProfileProvider.user; + Business? business = mzansiProfileProvider.business; + BusinessUser? businessUser = mzansiProfileProvider.businessUser; + String userProfilePictureUrl = + mzansiProfileProvider.userProfilePicUrl ?? ""; toolBodies.add( MihPersonalHome( - signedInUser: profData.signedInUser, - personalSelected: _personalSelected, - business: profData.business, - businessUser: profData.businessUser, - propicFile: profData.profilePicUrl != "" - ? NetworkImage(profData.profilePicUrl) + signedInUser: user!, + personalSelected: mzansiProfileProvider.personalHome, + business: business, + businessUser: businessUser, + propicFile: userProfilePictureUrl != "" + ? NetworkImage(userProfilePictureUrl) : null, isDevActive: AppEnviroment.getEnv() == "Dev", - isUserNew: profData.signedInUser.username == "", + isUserNew: user.username == "", ), ); - if (profData.signedInUser.type != "personal") { + if (user.type != "personal") { toolBodies.add( MihBusinessHome( - signedInUser: profData.signedInUser, - personalSelected: _personalSelected, - businessUser: profData.businessUser, - business: profData.business, - isBusinessUserNew: profData.businessUser == null, + isLoading: _isLoadingInitialData, ), ); } diff --git a/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart b/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart index b9b1ae12..acfb992f 100644 --- a/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart +++ b/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart @@ -4,10 +4,9 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tile/about_mih_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tiles/mih_calculator_tile.dart'; @@ -16,22 +15,15 @@ import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tiles/mzans import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_setup_business_profile_tile.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/package_tiles/pat_manager_tile.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/package_tiles/pat_manager_tile.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MihBusinessHome extends StatefulWidget { - final AppUser signedInUser; - final bool personalSelected; - final Business? business; - final BusinessUser? businessUser; - final bool isBusinessUserNew; + final bool isLoading; const MihBusinessHome({ super.key, - required this.signedInUser, - required this.personalSelected, - required this.business, - required this.businessUser, - required this.isBusinessUserNew, + required this.isLoading, }); @override @@ -70,7 +62,6 @@ class _MihBusinessHomeState extends State List> temp = []; temp.add({ "Setup Business": MzansiSetupBusinessProfileTile( - signedInUser: widget.signedInUser, packageSize: packageSize, ) }); @@ -78,15 +69,25 @@ class _MihBusinessHomeState extends State } List> setBusinessPackages() { + MzansiProfileProvider mzansiProfileProvider = + context.read(); + // if (mzansiProfileProvider.user == null || + // mzansiProfileProvider.business == null || + // mzansiProfileProvider.businessUser == null) { + // return []; // Return empty list if data isn't ready + // } List> temp = []; + if (mzansiProfileProvider.business == null && !widget.isLoading) { + temp.add({ + "Setup Business": MzansiSetupBusinessProfileTile( + packageSize: packageSize, + ) + }); + return temp; + } //=============== Biz Profile =============== temp.add({ "Business Profile": MzansiBusinessProfileTile( - arguments: BusinessArguments( - widget.signedInUser, - widget.businessUser, - widget.business, - ), packageSize: packageSize, ) }); @@ -94,10 +95,10 @@ class _MihBusinessHomeState extends State temp.add({ "Patient Manager": PatManagerTile( arguments: PatManagerArguments( - widget.signedInUser, + mzansiProfileProvider.user!, false, - widget.business, - widget.businessUser, + mzansiProfileProvider.business!, + mzansiProfileProvider.businessUser!, ), packageSize: packageSize, ) @@ -105,12 +106,6 @@ class _MihBusinessHomeState extends State //=============== Calendar =============== temp.add({ "Calendar": MzansiCalendarTile( - arguments: CalendarArguments( - widget.signedInUser, - false, - widget.business, - widget.businessUser, - ), packageSize: packageSize, ) }); @@ -118,24 +113,17 @@ class _MihBusinessHomeState extends State temp.add({ "Mzansi Directory": MzansiDirectoryTile( packageSize: packageSize, - personalSelected: false, ) }); //=============== Calculator =============== temp.add({ "Calculator": MihCalculatorTile( - personalSelected: widget.personalSelected, packageSize: packageSize, ) }); //=============== Mzansi AI =============== temp.add({ "Mzansi AI": MzansiAiTile( - arguments: MzansiAiArguments( - widget.signedInUser, - "", - false, - ), packageSize: packageSize, ) }); @@ -143,7 +131,6 @@ class _MihBusinessHomeState extends State temp.add({ "About MIH": AboutMihTile( packageSize: packageSize, - personalSelected: false, ) }); return temp; @@ -194,19 +181,9 @@ class _MihBusinessHomeState extends State void initState() { super.initState(); searchController.addListener(searchPackage); - if (widget.isBusinessUserNew) { - businessPackagesMap = setNewBusinessUserPackages(); - } else { - businessPackagesMap = setBusinessPackages(); - } + + businessPackagesMap = setBusinessPackages(); searchPackage(); - //Scrolling Banner message - // _marqueeController = AnimationController( - // vsync: this, - // duration: const Duration(seconds: 12), - // ); - // _scrollController = ScrollController(); - // WidgetsBinding.instance.addPostFrameCallback((_) => _startMarquee()); } @override @@ -221,123 +198,106 @@ class _MihBusinessHomeState extends State } Widget getBody(double width, double height) { - return MihSingleChildScroll( - child: Column( - children: [ - // Icon( - // MihIcons.mihLogo, - // size: width / 2, - // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // const SizedBox(height: 10), - // Text( - // // "Welcome, ${widget.signedInUser.fname}!", - // "Mzansi Innovation Hub", - // textAlign: TextAlign.center, - // style: TextStyle( - // fontSize: 30, - // fontWeight: FontWeight.bold, - // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // ), - // const SizedBox(height: 20), - Visibility( - visible: !widget.isBusinessUserNew, - child: Padding( - padding: EdgeInsets.symmetric(horizontal: width / 20), - child: MihSearchBar( - controller: searchController, - hintText: "Ask Mzansi", - prefixIcon: Icons.search, - prefixAltIcon: MihIcons.mzansiAi, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - hintColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onPrefixIconTap: () { - context.goNamed( - "mzansiAi", - extra: MzansiAiArguments( - widget.signedInUser, - searchController.text.isEmpty - ? null - : searchController.text, - false, - ), - ); - // Navigator.of(context).pushNamed( - // '/mzansi-ai', - // arguments: MzansiAiArguments( - // widget.signedInUser, - // searchController.text.isEmpty - // ? null - // : searchController.text, - // ), - // ); - searchController.clear(); - }, - searchFocusNode: _searchFocusNode, - ), - ), - ), - const SizedBox(height: 20), - ValueListenableBuilder( - valueListenable: searchPackageName, - builder: (context, value, child) { - List filteredPackages = value - .where((package) => package.keys.first - .toLowerCase() - .contains(searchController.text.toLowerCase())) - .map((package) => package.values.first) - .toList(); - if (filteredPackages.isNotEmpty) { - return GridView.builder( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - padding: getPadding(width, height), - // shrinkWrap: true, - itemCount: filteredPackages.length, - gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: packageSize, - crossAxisSpacing: 5, + return Consumer2( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, + MzansiAiProvider mzansiAiProvider, + Widget? child) { + // if (mzansiProfileProvider.user == null || + // mzansiProfileProvider.business == null || + // mzansiProfileProvider.businessUser == null) { + // return Center( + // child: Mihloadingcircle(), + // ); + // } + return MihSingleChildScroll( + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: Visibility( + visible: mzansiProfileProvider.business != null, + child: MihSearchBar( + controller: searchController, + hintText: "Ask Mzansi", + prefixIcon: Icons.search, + prefixAltIcon: MihIcons.mzansiAi, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + hintColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onPrefixIconTap: () { + mzansiAiProvider + .setStartUpQuestion(searchController.text); + context.goNamed( + "mzansiAi", + ); + searchController.clear(); + }, + searchFocusNode: _searchFocusNode, ), - itemBuilder: (context, index) { - return filteredPackages[index]; - }, - ); - } else { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 50), - Icon( - MihIcons.mzansiAi, - size: 165, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - const SizedBox(height: 10), - Text( - "Mzansi AI is here to help you!", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), + ), + ), + const SizedBox(height: 20), + ValueListenableBuilder( + valueListenable: searchPackageName, + builder: (context, value, child) { + List filteredPackages = value + .where((package) => package.keys.first + .toLowerCase() + .contains(searchController.text.toLowerCase())) + .map((package) => package.values.first) + .toList(); + if (filteredPackages.isNotEmpty) { + return GridView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: getPadding(width, height), + // shrinkWrap: true, + itemCount: filteredPackages.length, + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: packageSize, + crossAxisSpacing: 5, ), - ), - ], - ); - } - }, + itemBuilder: (context, index) { + return filteredPackages[index]; + }, + ); + } else { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.mzansiAi, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + const SizedBox(height: 10), + Text( + "Mzansi AI is here to help you!", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ], + ); + } + }, + ), + ], ), - ], - ), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart index 8c17cf56..6daf28fb 100644 --- a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart +++ b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart @@ -9,18 +9,21 @@ import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tile/about_mih_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/access_review/package_tile/mih_access_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tiles/mih_calculator_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/calendar/package_tiles/mzansi_calendar_tile.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/package_tiles/mih_mine_sweeper_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tiles/mzansi_ai_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_profile_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_setup_profile_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/package_tiles/mih_wallet_tile.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/package_tiles/patient_profile_tile.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/package_tiles/patient_profile_tile.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MihPersonalHome extends StatefulWidget { final AppUser signedInUser; @@ -78,8 +81,6 @@ class _MihPersonalHomeState extends State List> temp = []; temp.add({ "Setup Profile": MzansiSetupProfileTile( - signedInUser: widget.signedInUser, - propicFile: widget.propicFile, packageSize: packageSize, ) }); @@ -91,15 +92,12 @@ class _MihPersonalHomeState extends State //=============== Mzansi Profile =============== temp.add({ "Mzansi Profile": MzansiProfileTile( - signedInUser: widget.signedInUser, - propicFile: widget.propicFile, packageSize: packageSize, ) }); //=============== Mzansi Wallet =============== temp.add({ "Mzansi Wallet": MihWalletTile( - signedInUser: widget.signedInUser, packageSize: packageSize, ) }); @@ -120,35 +118,29 @@ class _MihPersonalHomeState extends State temp.add({ "Mzansi Directory": MzansiDirectoryTile( packageSize: packageSize, - personalSelected: true, ) }); //=============== Calendar =============== temp.add({ "Calendar": MzansiCalendarTile( - arguments: CalendarArguments( - widget.signedInUser, - true, - widget.business, - widget.businessUser, - ), packageSize: packageSize, ) }); //=============== Mzansi AI =============== temp.add({ "Mzansi AI": MzansiAiTile( - arguments: MzansiAiArguments( - widget.signedInUser, - "", - true, - ), packageSize: packageSize, ) }); //=============== Calculator =============== temp.add({ "Calculator": MihCalculatorTile( + packageSize: packageSize, + ) + }); + //=============== Mine Sweeper =============== + temp.add({ + "Mine Sweeper": MihMineSweeperTile( personalSelected: widget.personalSelected, packageSize: packageSize, ) @@ -156,7 +148,6 @@ class _MihPersonalHomeState extends State //=============== MIH Access =============== temp.add({ "MIH Access": MihAccessTile( - signedInUser: widget.signedInUser, packageSize: packageSize, ) }); @@ -164,7 +155,6 @@ class _MihPersonalHomeState extends State temp.add({ "About MIH": AboutMihTile( packageSize: packageSize, - personalSelected: true, ) }); //=============== Dev =============== @@ -259,124 +249,115 @@ class _MihPersonalHomeState extends State } Widget getBody(double width, double height) { - return MihSingleChildScroll( - child: Column( - children: [ - // Icon( - // MihIcons.mihLogo, - // size: 200, - // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // const SizedBox(height: 10), - // Text( - // // "Welcome, ${widget.signedInUser.fname}!", - // "Mzansi Innovation Hub", - // textAlign: TextAlign.center, - // style: TextStyle( - // fontSize: 30, - // fontWeight: FontWeight.bold, - // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // ), - // const SizedBox(height: 20), - Visibility( - visible: !widget.isUserNew, - child: Padding( - padding: EdgeInsets.symmetric(horizontal: width / 20), - child: MihSearchBar( - controller: searchController, - hintText: "Ask Mzansi", - prefixIcon: Icons.search, - prefixAltIcon: MihIcons.mzansiAi, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - hintColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onPrefixIconTap: () { - context.goNamed( - "mzansiAi", - extra: MzansiAiArguments( - widget.signedInUser, - searchController.text.isEmpty - ? null - : searchController.text, - true, - ), - ); - // Navigator.of(context).pushNamed( - // '/mzansi-ai', - // arguments: MzansiAiArguments( - // widget.signedInUser, - // searchController.text.isEmpty - // ? null - // : searchController.text, - // ), - // ); - searchController.clear(); - }, - searchFocusNode: _searchFocusNode, - ), - ), - ), - const SizedBox(height: 20), - ValueListenableBuilder( - valueListenable: searchPackageName, - builder: (context, value, child) { - List filteredPackages = value - .where((package) => package.keys.first - .toLowerCase() - .contains(searchController.text.toLowerCase())) - .map((package) => package.values.first) - .toList(); - if (filteredPackages.isNotEmpty) { - return GridView.builder( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - padding: getPadding(width, height), - // shrinkWrap: true, - itemCount: filteredPackages.length, - gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: packageSize, - crossAxisSpacing: 5, + return Consumer( + builder: (BuildContext context, MzansiAiProvider mzansiAiProvider, + Widget? child) { + return MihSingleChildScroll( + child: Column( + children: [ + // Icon( + // MihIcons.mihLogo, + // size: 200, + // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + // const SizedBox(height: 10), + // Text( + // // "Welcome, ${widget.signedInUser.fname}!", + // "Mzansi Innovation Hub", + // textAlign: TextAlign.center, + // style: TextStyle( + // fontSize: 30, + // fontWeight: FontWeight.bold, + // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + // ), + // const SizedBox(height: 20), + Visibility( + visible: !widget.isUserNew, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: MihSearchBar( + controller: searchController, + hintText: "Ask Mzansi", + prefixIcon: Icons.search, + prefixAltIcon: MihIcons.mzansiAi, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + hintColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onPrefixIconTap: () { + mzansiAiProvider + .setStartUpQuestion(searchController.text); + context.goNamed( + "mzansiAi", + ); + searchController.clear(); + }, + searchFocusNode: _searchFocusNode, ), - itemBuilder: (context, index) { - return filteredPackages[index]; - // return personalPackages[index]; - }, - ); - } else { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 50), - Icon( - MihIcons.mzansiAi, - size: 165, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - const SizedBox(height: 10), - Text( - "Mzansi AI is here to help you!", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), + ), + ), + const SizedBox(height: 20), + ValueListenableBuilder( + valueListenable: searchPackageName, + builder: (context, value, child) { + List filteredPackages = value + .where((package) => package.keys.first + .toLowerCase() + .contains(searchController.text.toLowerCase())) + .map((package) => package.values.first) + .toList(); + if (filteredPackages.isNotEmpty) { + return GridView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: getPadding(width, height), + // shrinkWrap: true, + itemCount: filteredPackages.length, + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: packageSize, + crossAxisSpacing: 5, ), - ), - ], - ); - } - }, + itemBuilder: (context, index) { + return filteredPackages[index]; + // return personalPackages[index]; + }, + ); + } else { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.mzansiAi, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + const SizedBox(height: 10), + Text( + "Mzansi AI is here to help you!", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ], + ); + } + }, + ), + ], ), - ], - ), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mine_sweeper/builders/build_minesweeper_leaderboard_list.dart b/Frontend/lib/mih_packages/mine_sweeper/builders/build_minesweeper_leaderboard_list.dart new file mode 100644 index 00000000..07b36218 --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/builders/build_minesweeper_leaderboard_list.dart @@ -0,0 +1,113 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:provider/provider.dart'; + +class BuildMinesweeperLeaderboardList extends StatefulWidget { + const BuildMinesweeperLeaderboardList({super.key}); + + @override + State createState() => + _BuildMinesweeperLeaderboardListState(); +} + +class _BuildMinesweeperLeaderboardListState + extends State { + Color getMedalColor(int index) { + switch (index) { + case (0): + return MihColors.getGoldColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + case (1): + return MihColors.getSilverColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + case (2): + return MihColors.getBronze( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + default: + return MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } + } + + @override + Widget build(BuildContext context) { + final double width = MediaQuery.sizeOf(context).width; + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + MihMineSweeperProvider mineSweeperProvider, Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, index) { + return Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + itemCount: mineSweeperProvider.leaderboard!.length, + itemBuilder: (context, index) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: Row( + children: [ + Text( + "#${index + 1}", + style: TextStyle( + fontSize: 25, + color: getMedalColor(index), + ), + ), + const SizedBox(width: 10), + MihCircleAvatar( + key: UniqueKey(), + imageFile: + mineSweeperProvider.leaderboardUserPictures.isNotEmpty + ? mineSweeperProvider.leaderboardUserPictures[index] + : null, + width: 80, + editable: false, + fileNameController: null, + userSelectedfile: null, + frameColor: getMedalColor(index), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onChange: () {}, + ), + const SizedBox(width: 10), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "${mineSweeperProvider.leaderboard![index].username}${profileProvider.user!.username == mineSweeperProvider.leaderboard![index].username ? " (You)" : ""}", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: getMedalColor(index), + ), + ), + Text( + "Score: ${mineSweeperProvider.leaderboard![index].game_score}\nTime: ${mineSweeperProvider.leaderboard![index].game_time}", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 18, + // fontWeight: FontWeight.bold, + color: getMedalColor(index), + ), + ), + ], + ) + ], + ), + ); + }, + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mine_sweeper/builders/build_my_scoreboard_list.dart b/Frontend/lib/mih_packages/mine_sweeper/builders/build_my_scoreboard_list.dart new file mode 100644 index 00000000..58dc3b23 --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/builders/build_my_scoreboard_list.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:provider/provider.dart'; + +class BuildMyScoreBoardList extends StatefulWidget { + const BuildMyScoreBoardList({super.key}); + + @override + State createState() => + _BuildMinesweeperLeaderboardListState(); +} + +class _BuildMinesweeperLeaderboardListState + extends State { + Color getMedalColor(int index) { + switch (index) { + case (0): + return MihColors.getGoldColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + case (1): + return MihColors.getSilverColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + case (2): + return MihColors.getBronze( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + default: + return MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } + } + + @override + Widget build(BuildContext context) { + final double width = MediaQuery.sizeOf(context).width; + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + MihMineSweeperProvider mineSweeperProvider, Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, index) { + return Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + itemCount: mineSweeperProvider.myScoreboard!.length, + itemBuilder: (context, index) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: Row( + children: [ + Text( + "#${index + 1}", + style: TextStyle( + fontSize: 25, + color: getMedalColor(index), + ), + ), + const SizedBox(width: 10), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Score: ${mineSweeperProvider.myScoreboard![index].game_score}", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: getMedalColor(index), + ), + ), + Text( + "Time: ${mineSweeperProvider.myScoreboard![index].game_time}", + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 18, + // fontWeight: FontWeight.bold, + color: getMedalColor(index), + ), + ), + ], + ) + ], + ), + ); + }, + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mine_sweeper/components/board_square.dart b/Frontend/lib/mih_packages/mine_sweeper/components/board_square.dart new file mode 100644 index 00000000..0259b064 --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/components/board_square.dart @@ -0,0 +1,13 @@ +class BoardSquare { + bool hasBomb; + int bombsAround; + bool isOpened; + bool isFlagged; + + BoardSquare({ + this.hasBomb = false, + this.bombsAround = 0, + this.isOpened = false, + this.isFlagged = false, + }); +} diff --git a/Frontend/lib/mih_packages/mine_sweeper/components/leaderboard_user_ranking.dart b/Frontend/lib/mih_packages/mine_sweeper/components/leaderboard_user_ranking.dart new file mode 100644 index 00000000..e2c4feb2 --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/components/leaderboard_user_ranking.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; +import 'package:ken_logger/ken_logger.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:redacted/redacted.dart'; + +class LeaderboardUserRanking extends StatelessWidget { + final int index; + final String proPicUrl; + final String username; + final dynamic gameScore; + final String gameTime; + final bool isCurrentUser; + final Future?> Function(String) getUserPicture; + + const LeaderboardUserRanking({ + super.key, + required this.index, + required this.proPicUrl, + required this.username, + required this.gameScore, + required this.gameTime, + required this.isCurrentUser, + required this.getUserPicture, + }); + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: getUserPicture(proPicUrl), + builder: (context, asyncSnapshot) { + bool isLoading = + asyncSnapshot.connectionState == ConnectionState.waiting; + + KenLogger.success("URL: ${asyncSnapshot.data.toString()}"); + return ListTile( + leading: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "#${index + 1}", + style: const TextStyle( + fontSize: 25, + ), + ), + const SizedBox(width: 10), + MihCircleAvatar( + key: ValueKey(asyncSnapshot.data + .toString()), // Use ValueKey for stable identity + imageFile: asyncSnapshot.data, + width: 60, + editable: false, + fileNameController: null, + userSelectedfile: null, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onChange: () {}, + ), + ], + ), + title: Text( + "$username${isCurrentUser ? " (You)" : ""}", + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ).redacted(context: context, redact: isLoading), + subtitle: Text( + "Score: $gameScore\nTime: $gameTime", + style: TextStyle( + fontSize: 18, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ).redacted(context: context, redact: isLoading), + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mine_sweeper/components/mih_mine_sweeper_start_game_window.dart b/Frontend/lib/mih_packages/mine_sweeper/components/mih_mine_sweeper_start_game_window.dart new file mode 100644 index 00000000..3ec5092e --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/components/mih_mine_sweeper_start_game_window.dart @@ -0,0 +1,174 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:provider/provider.dart'; + +class MihMineSweeperStartGameWindow extends StatefulWidget { + final void Function()? onPressed; + const MihMineSweeperStartGameWindow({ + super.key, + required this.onPressed, + }); + + @override + State createState() => + _MihMineSweeperStartGameWindowState(); +} + +class _MihMineSweeperStartGameWindowState + extends State { + TextEditingController modeController = TextEditingController(); + final _formKey = GlobalKey(); + + void applyGameSettings(MihMineSweeperProvider mihMineSweeperProvider) { + mihMineSweeperProvider.setDifficulty(modeController.text); + switch (mihMineSweeperProvider.difficulty) { + case ("Very Easy"): + mihMineSweeperProvider.setRowCount(6); + mihMineSweeperProvider.setCoulmnCount(6); + mihMineSweeperProvider.setTotalMines(5); + // mihMineSweeperProvider.setRowCount(5); + // mihMineSweeperProvider.setCoulmnCount(5); + // mihMineSweeperProvider.setTotalMines(3); + break; + case ("Easy"): + mihMineSweeperProvider.setRowCount(8); + mihMineSweeperProvider.setCoulmnCount(8); + mihMineSweeperProvider.setTotalMines(10); + // mihMineSweeperProvider.setRowCount(10); + // mihMineSweeperProvider.setCoulmnCount(10); + // mihMineSweeperProvider.setTotalMines(15); + break; + case ("Intermediate"): + mihMineSweeperProvider.setRowCount(10); + mihMineSweeperProvider.setCoulmnCount(10); + mihMineSweeperProvider.setTotalMines(18); + // mihMineSweeperProvider.setRowCount(15); + // mihMineSweeperProvider.setCoulmnCount(10); + // mihMineSweeperProvider.setTotalMines(23); + break; + case ("Hard"): + mihMineSweeperProvider.setRowCount(12); + mihMineSweeperProvider.setCoulmnCount(10); + mihMineSweeperProvider.setTotalMines(30); + // mihMineSweeperProvider.setRowCount(20); + // mihMineSweeperProvider.setCoulmnCount(10); + // mihMineSweeperProvider.setTotalMines(30); + break; + default: + break; + } + } + + String getModeConfig() { + switch (modeController.text) { + case ("Very Easy"): + return "Columns: 6\nRows: 6\nBombs: 5"; + case ("Easy"): + return "Columns: 8\nRows: 8\nBombs: 10"; + case ("Intermediate"): + return "Columns: 10\nRows: 10\nBombs: 18"; + case ("Hard"): + return "Columns: 10\nRows: 12\nBombs: 30"; + default: + return "Error"; + } + } + + void _onModeChanged() { + setState(() {}); + } + + @override + void dispose() { + modeController.removeListener(_onModeChanged); + modeController.dispose(); + super.dispose(); + } + + @override + void initState() { + super.initState(); + modeController.text = context.read().difficulty; + modeController.addListener(_onModeChanged); + } + + @override + Widget build(BuildContext context) { + return MihPackageWindow( + fullscreen: false, + windowTitle: "New Game Settings", + onWindowTapClose: () { + context.pop(); + }, + windowBody: Consumer( + builder: (BuildContext context, + MihMineSweeperProvider mihMineSweeperProvider, Widget? child) { + return Column( + children: [ + MihForm( + formKey: _formKey, + formFields: [ + MihDropdownField( + controller: modeController, + hintText: "Difficulty", + dropdownOptions: [ + "Very Easy", + "Easy", + "Intermediate", + "Hard" + ], + requiredText: true, + editable: true, + enableSearch: false, + ), + const SizedBox(height: 10), + Text( + getModeConfig(), + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + applyGameSettings(mihMineSweeperProvider); + context.pop(); + widget.onPressed?.call(); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Start Game", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ], + ); + }, + ), + ); + } +} diff --git a/Frontend/lib/mih_packages/mine_sweeper/components/mine_tile.dart b/Frontend/lib/mih_packages/mine_sweeper/components/mine_tile.dart new file mode 100644 index 00000000..f6e653d8 --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/components/mine_tile.dart @@ -0,0 +1,112 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/components/board_square.dart'; + +class MineTile extends StatelessWidget { + final BoardSquare square; + final VoidCallback onTap; + final VoidCallback onLongPress; + + const MineTile({ + super.key, + required this.square, + required this.onTap, + required this.onLongPress, + }); + + Widget _getTileContent(BuildContext context) { + if (square.isFlagged) { + return Icon( + Icons.flag, + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode != "Dark", + ), + ); + } + + if (square.isOpened) { + if (square.hasBomb) { + return const Icon(FontAwesomeIcons.bomb, color: Colors.black); + } else if (square.bombsAround > 0) { + // Display bomb count + return Center( + child: Text( + '${square.bombsAround}', + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: _getTileColor(square.bombsAround, context), + ), + ), + ); + } else { + // Opened, but no bomb count (empty square) + return const SizedBox.shrink(); + } + } + + // Default: Unopened tile + return const SizedBox.shrink(); + } + + Color _getTileColor(int bombsAround, BuildContext context) { + // Choose colors based on standard Minesweeper appearance + switch (bombsAround) { + case 1: + return MihColors.getBluishPurpleColor( + MzansiInnovationHub.of(context)!.theme.mode != "Dark", + ); + // return Colors.blue; + case 2: + return MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode != "Dark", + ); + // return Colors.green; + case 3: + return MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode != "Dark", + ); + // return Colors.red; + case 4: + return MihColors.getPurpleColor( + MzansiInnovationHub.of(context)!.theme.mode != "Dark", + ); + // return Colors.purple; + case 5: + return MihColors.getOrangeColor( + MzansiInnovationHub.of(context)!.theme.mode != "Dark", + ); + // return Colors.brown; + default: + // return MihColors.getBluishPurpleColor( + // MzansiInnovationHub.of(context)!.theme.mode == "Dark", + // ); + return Colors.black; + } + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(1.0), + child: MihButton( + onPressed: onTap, + onLongPressed: onLongPress, + buttonColor: square.isOpened + ? MihColors.getGreyColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark", + ) + : MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark", + ), + width: 50, + height: 50, + borderRadius: 3, + child: _getTileContent(context), + ), + ); + } +} diff --git a/Frontend/lib/mih_packages/mine_sweeper/mih_mine_sweeper.dart b/Frontend/lib/mih_packages/mine_sweeper/mih_mine_sweeper.dart new file mode 100644 index 00000000..ef545c7a --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/mih_mine_sweeper.dart @@ -0,0 +1,101 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/package_tools/mih_mine_sweeper_leader_board.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/package_tools/mine_sweeper_game.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/package_tools/mine_sweeper_quick_start_guide.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/package_tools/my_score_board.dart'; +import 'package:provider/provider.dart'; + +class MihMineSweeper extends StatefulWidget { + const MihMineSweeper({super.key}); + + @override + State createState() => _MihMineSweeperState(); +} + +class _MihMineSweeperState extends State { + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) async { + context.read().loadBannerAd(); + }); + } + + @override + Widget build(BuildContext context) { + return MihPackage( + appActionButton: getAction(), + appTools: getTools(), + appToolTitles: getToolTitle(), + appBody: getToolBody(), + selectedbodyIndex: context.watch().toolIndex, + onIndexChange: (newIndex) { + context.read().setToolIndex(newIndex); + }, + ); + } + + MihPackageAction getAction() { + return MihPackageAction( + icon: const Icon(Icons.arrow_back), + iconSize: 35, + onTap: () { + MihMineSweeperProvider mineSweeperProvider = + context.read(); + mineSweeperProvider.setToolIndex(0); + mineSweeperProvider.setDifficulty("Easy"); + context.goNamed( + 'mihHome', + ); + FocusScope.of(context).unfocus(); + }, + ); + } + + MihPackageTools getTools() { + Map temp = {}; + temp[const Icon(FontAwesomeIcons.bomb)] = () { + context.read().setToolIndex(0); + }; + temp[const Icon(Icons.leaderboard_rounded)] = () { + context.read().setToolIndex(1); + }; + temp[const Icon(Icons.perm_identity_rounded)] = () { + context.read().setToolIndex(2); + }; + temp[const Icon(Icons.rule_rounded)] = () { + context.read().setToolIndex(3); + }; + return MihPackageTools( + tools: temp, + selcetedIndex: context.watch().toolIndex, + ); + } + + List getToolTitle() { + List toolTitles = [ + "Minesweeper", + "Leader Board", + "My Scores", + "Guide", + ]; + return toolTitles; + } + + List getToolBody() { + List toolBodies = [ + const MineSweeperGame(), + const MihMineSweeperLeaderBoard(), + const MyScoreBoard(), + const MineSweeperQuickStartGuide(), + ]; + return toolBodies; + } +} diff --git a/Frontend/lib/mih_packages/mine_sweeper/package_tiles/mih_mine_sweeper_tile.dart b/Frontend/lib/mih_packages/mine_sweeper/package_tiles/mih_mine_sweeper_tile.dart new file mode 100644 index 00000000..9654cfcb --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/package_tiles/mih_mine_sweeper_tile.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; + +class MihMineSweeperTile extends StatefulWidget { + final bool personalSelected; + final double packageSize; + const MihMineSweeperTile({ + super.key, + required this.personalSelected, + required this.packageSize, + }); + + @override + State createState() => _MihMineSweeperTileState(); +} + +class _MihMineSweeperTileState extends State { + @override + Widget build(BuildContext context) { + return MihPackageTile( + onTap: () { + context.goNamed( + "mihMinesweeper", + ); + }, + appName: "Minesweeper", + appIcon: Icon( + MihIcons.mineSweeper, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // size: widget.packageSize, + ), + iconSize: widget.packageSize, + primaryColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + secondaryColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + } +} diff --git a/Frontend/lib/mih_packages/mine_sweeper/package_tools/mih_mine_sweeper_leader_board.dart b/Frontend/lib/mih_packages/mine_sweeper/package_tools/mih_mine_sweeper_leader_board.dart new file mode 100644 index 00000000..b7f62cab --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/package_tools/mih_mine_sweeper_leader_board.dart @@ -0,0 +1,198 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:ken_logger/ken_logger.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/builders/build_minesweeper_leaderboard_list.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_minesweeper_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; + +class MihMineSweeperLeaderBoard extends StatefulWidget { + const MihMineSweeperLeaderBoard({super.key}); + + @override + State createState() => + _MihMineSweeperLeaderBoardState(); +} + +class _MihMineSweeperLeaderBoardState extends State { + TextEditingController filterController = TextEditingController(); + + Future initialiseLeaderboard() async { + MihMineSweeperProvider mineSweeperProvider = + context.read(); + filterController.text = mineSweeperProvider.difficulty; + KenLogger.success("getting data"); + await MihMinesweeperServices().getTop20Leaderboard(mineSweeperProvider); + List?> userPictures = []; + String userPicUrl = ""; + for (final ranking in mineSweeperProvider.leaderboard!) { + userPicUrl = await MihFileApi.getMinioFileUrl(ranking.proPicUrl, context); + userPictures.add(NetworkImage(userPicUrl)); + } + mineSweeperProvider.setLeaderboardUserPictures( + leaderboardUserPictures: userPictures); + } + + void refreshLeaderBoard( + MihMineSweeperProvider mineSweeperProvider, String difficulty) { + mineSweeperProvider.setDifficulty(difficulty); + mineSweeperProvider.setLeaderboard(leaderboard: null); + mineSweeperProvider.setMyScoreboard(myScoreboard: null); + initialiseLeaderboard(); + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) async { + await initialiseLeaderboard(); + }); + } + + @override + Widget build(BuildContext context) { + final double width = MediaQuery.sizeOf(context).width; + return Consumer( + builder: (BuildContext context, + MihMineSweeperProvider mineSweeperProvider, Widget? child) { + return RefreshIndicator( + onRefresh: () async { + refreshLeaderBoard(mineSweeperProvider, filterController.text); + }, + child: MihPackageToolBody( + borderOn: false, + bodyItem: getBody(width), + ), + ); + }, + ); + } + + Widget getBody(double width) { + return Consumer( + builder: (BuildContext context, + MihMineSweeperProvider mineSweeperProvider, Widget? child) { + if (mineSweeperProvider.leaderboard == null) { + return Center( + child: Mihloadingcircle(), + ); + } else { + return SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: MihDropdownField( + controller: filterController, + hintText: "Leaderboards", + dropdownOptions: const [ + "Very Easy", + "Easy", + "Intermediate", + "Hard", + ], + requiredText: true, + editable: true, + enableSearch: false, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + onSelected: (selection) { + refreshLeaderBoard(mineSweeperProvider, selection!); + }, + ), + ), + ], + ), + ), + const SizedBox(height: 10), + mineSweeperProvider.leaderboard!.isEmpty + ? Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.mineSweeper, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + const SizedBox(height: 10), + Text( + "Be the first on the leaderboard.", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + const SizedBox(height: 25), + Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.normal, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + children: [ + TextSpan(text: "Press "), + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Icon( + FontAwesomeIcons.bomb, + size: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + TextSpan(text: " and start a new game"), + ], + ), + ), + ), + ], + ), + ) + : BuildMinesweeperLeaderboardList(), + ], + ), + ); + } + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mine_sweeper/package_tools/mine_sweeper_game.dart b/Frontend/lib/mih_packages/mine_sweeper/package_tools/mine_sweeper_game.dart new file mode 100644 index 00000000..6a4b2ce6 --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/package_tools/mine_sweeper_game.dart @@ -0,0 +1,813 @@ +import 'dart:async'; +import 'dart:math'; +import 'package:flutter/material.dart'; +import 'package:flutter_speed_dial/flutter_speed_dial.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_banner_ad.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/components/board_square.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/components/mih_mine_sweeper_start_game_window.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/components/mine_tile.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_minesweeper_services.dart'; +import 'package:provider/provider.dart'; + +class MineSweeperGame extends StatefulWidget { + const MineSweeperGame({super.key}); + + @override + State createState() => _MineSweeperGameState(); +} + +class _MineSweeperGameState extends State { + List> board = []; + bool isGameOver = false; + bool isGameWon = false; + int squaresLeft = -1; + Timer? _timer; + int _milliseconds = 0; + bool _isRunning = false; + static const int millisecondsPerUpdate = 100; + + double timeStringToTotalSeconds(String timeString) { + try { + List parts = timeString.split(':'); + if (parts.length != 4) { + return 0.0; + } + double hours = double.parse(parts[0]); + double minutes = double.parse(parts[1]); + double seconds = double.parse(parts[2]); + double milliseconds = double.parse(parts[3]); + double totalSeconds = + (hours * 3600) + (minutes * 60) + seconds + (milliseconds / 100); + return totalSeconds; + } catch (e) { + print("Error parsing time string: $e"); + return 0.0; + } + } + + double calculateGameScore(MihMineSweeperProvider mihMineSweeperProvider) { + int scoreConst = 10000; + double dificusltyMultiplier; + switch (mihMineSweeperProvider.difficulty) { + case ("Very Easy"): + dificusltyMultiplier = 0.5; + break; + case ("Easy"): + dificusltyMultiplier = 1.0; + break; + case ("Intermediate"): + dificusltyMultiplier = 2.5; + break; + case ("Hard"): + dificusltyMultiplier = 5.0; + break; + default: + dificusltyMultiplier = 0.0; + break; + } + double rawScore = (scoreConst * dificusltyMultiplier) / + timeStringToTotalSeconds(_formatTime()); + + String scoreString = rawScore.toStringAsFixed(5); + return double.parse(scoreString); + } + + void startTimer() { + if (_isRunning) return; + _isRunning = true; + _timer = Timer.periodic(const Duration(milliseconds: millisecondsPerUpdate), + (timer) { + setState(() { + _milliseconds += millisecondsPerUpdate; // Increment by the interval + }); + }); + } + + void stopTimer() { + _timer?.cancel(); + setState(() { + _isRunning = false; + }); + } + + void resetTimer() { + stopTimer(); // Stop the timer first + setState(() { + _milliseconds = 0; // Reset the time to zero + }); + } + + String _formatTime() { + Duration duration = Duration(milliseconds: _milliseconds); + final int hours = duration.inHours; + final int minutes = duration.inMinutes.remainder(60); + final int seconds = duration.inSeconds.remainder(60); + final int centiseconds = (duration.inMilliseconds.remainder(1000)) ~/ 10; + String hoursStr = hours.toString().padLeft(2, '0'); + String minutesStr = minutes.toString().padLeft(2, '0'); + String secondsStr = seconds.toString().padLeft(2, '0'); + String centiStr = centiseconds.toString().padLeft(2, '0'); + return '$hoursStr:$minutesStr:$secondsStr:$centiStr'; + } + + void showStartGameWindow(MihMineSweeperProvider mihMineSweeperProvider, + MihBannerAdProvider addProvider) { + // easy - 10 * 10 & 15 bombs + // Intermediate - 10 * 15 & 23 bombs + // Hard - 10 * 20 & 30 bombs + addProvider.loadBannerAd(); + showDialog( + context: context, + builder: (context) { + return MihMineSweeperStartGameWindow( + onPressed: () { + resetTimer(); + mihMineSweeperProvider + .setDifficulty(mihMineSweeperProvider.difficulty); + setState(() => initializeBoard(mihMineSweeperProvider)); + }, + ); + }); + } + +// --- GAME INITIALIZATION LOGIC --- + void initializeBoard(MihMineSweeperProvider mihMineSweeperProvider) { + // 1. Create a board of empty squares + board = List.generate( + mihMineSweeperProvider.rowCount, + (i) => List.generate( + mihMineSweeperProvider.columnCount, + (j) => BoardSquare(), + ), + ); + // 2. Place bombs randomly + placeBombs(mihMineSweeperProvider); + // 3. Calculate the number of bombs around each non-mine square + calculateBombsAround(mihMineSweeperProvider); + // Reset state variables + squaresLeft = + mihMineSweeperProvider.rowCount * mihMineSweeperProvider.columnCount; + isGameOver = false; + isGameWon = false; + // You'd typically add a call to setState here, but it's in initState. + startTimer(); + } + + void placeBombs(MihMineSweeperProvider mihMineSweeperProvider) { + final Random random = Random(); + int bombsPlaced = 0; + + while (bombsPlaced < mihMineSweeperProvider.totalMines) { + int r = random.nextInt(mihMineSweeperProvider.rowCount); + int c = random.nextInt(mihMineSweeperProvider.columnCount); + + if (!board[r][c].hasBomb) { + board[r][c].hasBomb = true; + bombsPlaced++; + } + } + } + + void calculateBombsAround(MihMineSweeperProvider mihMineSweeperProvider) { + for (int r = 0; r < mihMineSweeperProvider.rowCount; r++) { + for (int c = 0; c < mihMineSweeperProvider.columnCount; c++) { + if (!board[r][c].hasBomb) { + int count = 0; + + // Check the 8 neighbors + for (int i = -1; i <= 1; i++) { + for (int j = -1; j <= 1; j++) { + if (i == 0 && j == 0) continue; // Skip the current square + + int neighborR = r + i; + int neighborC = c + j; + + // Check if neighbor is within bounds + if (neighborR >= 0 && + neighborR < mihMineSweeperProvider.rowCount && + neighborC >= 0 && + neighborC < mihMineSweeperProvider.columnCount) { + if (board[neighborR][neighborC].hasBomb) { + count++; + } + } + } + } + board[r][c].bombsAround = count; + } + } + } + } + + // Handles recursive opening of zero-squares + void _expandZeros( + MihMineSweeperProvider mihMineSweeperProvider, int r, int c) { + if (r < 0 || + r >= mihMineSweeperProvider.rowCount || + c < 0 || + c >= mihMineSweeperProvider.columnCount || + board[r][c].isOpened) { + return; + } + + BoardSquare square = board[r][c]; + + // Open the current square + square.isOpened = true; + squaresLeft--; + + // If it's a zero square, recursively call for neighbors + if (square.bombsAround == 0) { + // Check all 8 neighbors (not just 4 sides, for standard Minesweeper expansion) + for (int i = -1; i <= 1; i++) { + for (int j = -1; j <= 1; j++) { + _expandZeros(mihMineSweeperProvider, r + i, c + j); + } + } + } + } + + Future handleTap( + MzansiProfileProvider profileProvider, + MihMineSweeperProvider mihMineSweeperProvider, + MihBannerAdProvider adProvider, + int r, + int c) async { + if (isGameOver || board[r][c].isOpened || board[r][c].isFlagged) { + return; + } + // 1. Check for bomb (LOSS) + if (board[r][c].hasBomb) { + stopTimer(); + setState(() { + board[r][c].isOpened = true; + isGameOver = true; + // lose alert + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon( + FontAwesomeIcons.bomb, + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + size: 100, + ), + ), + alertTitle: "Better Luck Next Time", + alertBody: Column( + children: [ + Text( + "Your lost this game of MIH Minesweeper!!!", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + const SizedBox(height: 10), + Text( + "Please feel free to start a New Game or check out the Leader Board to find out who's the best in Mzansi.", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + const SizedBox(height: 20), + Wrap( + runAlignment: WrapAlignment.center, + crossAxisAlignment: WrapCrossAlignment.center, + spacing: 10, + runSpacing: 10, + children: [ + MihButton( + onPressed: () { + context.pop(); + showStartGameWindow( + mihMineSweeperProvider, adProvider); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "New Game", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + MihButton( + onPressed: () { + context.pop(); + mihMineSweeperProvider.setToolIndex(1); + }, + buttonColor: MihColors.getOrangeColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Leader Board", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ], + ), + alertColour: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + ); + }); + return; + } + // 2. Open square and handle expansion (RECURSION) + if (board[r][c].bombsAround == 0) { + // Start recursive expansion + _expandZeros(mihMineSweeperProvider, r, c); + } else { + // Just open the single square + board[r][c].isOpened = true; + squaresLeft--; + } + // 3. Check for win + _checkWinCondition(profileProvider, mihMineSweeperProvider, adProvider); + // Update the UI + setState(() {}); + } + + void handleLongPress(int r, int c) { + if (isGameOver || board[r][c].isOpened) { + return; + } + setState(() { + // Toggle the flag status + board[r][c].isFlagged = !board[r][c].isFlagged; + }); + } + + // --- GAME ACTION LOGIC --- + Future _checkWinCondition( + MzansiProfileProvider profileProvider, + MihMineSweeperProvider mihMineSweeperProvider, + MihBannerAdProvider adProvider, + ) async { + // Game is won if all non-mine squares are opened. + if (squaresLeft <= mihMineSweeperProvider.totalMines) { + stopTimer(); + isGameWon = true; + isGameOver = true; + // win alert + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.celebration, + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + size: 100, + ), + alertTitle: "Congratulations", + alertBody: Column( + children: [ + Text( + "Your won this game of MIH Minesweeper!!!", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + const SizedBox(height: 10), + // Text( + // "You took ${_formatTime()} to complete the game on ${mihMineSweeperProvider.difficulty} mode.", + // style: TextStyle( + // fontSize: 15, + // color: MihColors.getSecondaryColor( + // MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + // ), + // const SizedBox(height: 10), + Text( + "Time Taken: ${_formatTime().replaceAll("00:", "")}", + style: TextStyle( + fontSize: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + const SizedBox(height: 10), + Text( + "Score: ${calculateGameScore(mihMineSweeperProvider)}", + style: TextStyle( + fontSize: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + const SizedBox(height: 20), + Wrap( + runAlignment: WrapAlignment.center, + crossAxisAlignment: WrapCrossAlignment.center, + spacing: 10, + runSpacing: 10, + children: [ + MihButton( + onPressed: () { + context.pop(); + showStartGameWindow(mihMineSweeperProvider, adProvider); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "New Game", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + MihButton( + onPressed: () { + context.pop(); + mihMineSweeperProvider.setToolIndex(1); + }, + buttonColor: MihColors.getOrangeColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Leader Board", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ], + ), + alertColour: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + ); + showDialog( + context: context, + builder: (context) { + return Mihloadingcircle( + message: "Uploading your score", + ); + }); + await MihMinesweeperServices().addPlayerScore( + profileProvider, + mihMineSweeperProvider, + _formatTime().replaceAll("00:", ""), + calculateGameScore(mihMineSweeperProvider), + ); + context.pop(); + } + } + + Color? getDifficultyColor(MihMineSweeperProvider mihMineSweeperProvider) { + String mode = mihMineSweeperProvider.difficulty; + switch (mode) { + case "Very Easy": + return MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark", + ); + case "Easy": + return MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode != "Dark", + ); + case "Intermediate": + return MihColors.getOrangeColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark", + ); + case "Hard": + return MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark", + ); + default: + return null; + } + } + + @override + void dispose() { + _timer?.cancel(); + super.dispose(); + } + + @override + void initState() { + // UBongani was here during the MIH Live + super.initState(); + } + + @override + Widget build(BuildContext context) { + return MihPackageToolBody( + borderOn: false, + bodyItem: getBody(), + ); + } + + Widget getBody() { + return Consumer3( + builder: (BuildContext context, + MzansiProfileProvider profileProvider, + MihMineSweeperProvider mihMineSweeperProvider, + MihBannerAdProvider adProvider, + Widget? child) { + return Column( + children: [ + Expanded( + child: Stack( + alignment: Alignment.topCenter, + children: [ + MihSingleChildScroll( + child: board.isEmpty && squaresLeft < 0 + // Start Up Message before setting up game + ? Padding( + padding: + const EdgeInsets.symmetric(horizontal: 10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.mineSweeper, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + const SizedBox(height: 10), + Text( + "Welcom to Minesweeper, the first game of MIH.", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + const SizedBox(height: 25), + Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.normal, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + children: [ + TextSpan(text: "Press "), + WidgetSpan( + alignment: + PlaceholderAlignment.middle, + child: Icon( + Icons.menu, + size: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + TextSpan( + text: + " to start a new game or learn how to play the minesweeper."), + ], + ), + ), + ), + ], + ), + ) + // Display Game Board when game started + : Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // Display game status + Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10.0), + child: Text( + 'Mines: ${mihMineSweeperProvider.totalMines}', + textAlign: TextAlign.left, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold), + ), + ), + ), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10.0), + child: Text( + _formatTime().replaceAll("00:", ""), + textAlign: TextAlign.right, + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold), + ), + ), + ), + ], + ), + Text( + mihMineSweeperProvider.difficulty, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: getDifficultyColor( + mihMineSweeperProvider), + ), + ), + + // const SizedBox( + // height: 30, + // ), + // The Board Grid + SizedBox( + width: mihMineSweeperProvider.columnCount * + 40.0, // Control size based on columns + height: mihMineSweeperProvider.rowCount * + 40.0, // Control size based on rows + child: GridView.builder( + physics: + const NeverScrollableScrollPhysics(), // Prevent scrolling + gridDelegate: + SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: + mihMineSweeperProvider.columnCount, + crossAxisSpacing: 0, + mainAxisSpacing: 0, + ), + itemCount: mihMineSweeperProvider.rowCount * + mihMineSweeperProvider.columnCount, + itemBuilder: (context, index) { + int r = index ~/ + mihMineSweeperProvider + .columnCount; // Integer division for row + int c = index % + mihMineSweeperProvider + .columnCount; // Remainder for column + + return MineTile( + square: board[r][c], + onTap: () => handleTap( + profileProvider, + mihMineSweeperProvider, + adProvider, + r, + c), + onLongPress: () => handleLongPress(r, c), + ); + }, + ), + ), + SizedBox(height: 30), + // const SizedBox(height: 100), + ], + ), + ), + Positioned( + right: 10, + bottom: 10, + child: MihFloatingMenu( + animatedIcon: AnimatedIcons.menu_close, + children: [ + SpeedDialChild( + child: Icon( + Icons.rule_rounded, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + label: "Learn how to play", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onTap: () { + mihMineSweeperProvider.setToolIndex(2); + }, + ), + SpeedDialChild( + child: Icon( + Icons.add, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + label: board.isEmpty && squaresLeft < 0 + ? "Start Game" + : "Reset Game", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onTap: () { + showStartGameWindow( + mihMineSweeperProvider, adProvider); + }, + ), + ]), + ) + ], + ), + ), + MihBannerAd(), + SizedBox(height: 15), + ], + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mine_sweeper/package_tools/mine_sweeper_quick_start_guide.dart b/Frontend/lib/mih_packages/mine_sweeper/package_tools/mine_sweeper_quick_start_guide.dart new file mode 100644 index 00000000..2bd762c7 --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/package_tools/mine_sweeper_quick_start_guide.dart @@ -0,0 +1,350 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; + +class MineSweeperQuickStartGuide extends StatefulWidget { + const MineSweeperQuickStartGuide({super.key}); + + @override + State createState() => + _MineSweeperQuickStartGuideState(); +} + +class _MineSweeperQuickStartGuideState + extends State { + Widget _buildSectionTitle(String title) { + return Text( + title, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 22, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ); + } + + Widget _buildSubSectionTitle(String title) { + return Text( + title, + style: TextStyle( + fontSize: 17, + fontWeight: FontWeight.w600, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ); + } + + Widget _buildRulePoint({ + required String title, + required List points, + required Color color, + }) { + return Padding( + padding: + const EdgeInsets.only(left: 8.0, right: 8.0, top: 4.0, bottom: 4.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: color, + ), + ), + ...points + .map((point) => Padding( + padding: const EdgeInsets.only(left: 10.0), + child: Text( + '• $point', + style: TextStyle( + fontSize: 16, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + )) + .toList(), + ], + ), + ); + } + + Widget _buildNumberClue(String clue, String explanation) { + return Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 4.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('• ', + style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), + Expanded( + child: RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16, + color: MihColors.getOrangeColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark")), + children: [ + TextSpan( + text: 'If you see a $clue: ', + style: const TextStyle(fontWeight: FontWeight.bold)), + TextSpan(text: explanation), + ], + ), + ), + ), + ], + ), + ); + } + + Widget _buildStrategyPoint(String title, String explanation, + {bool isAction = false}) { + return Padding( + padding: const EdgeInsets.only(right: 8.0, left: 8.0, bottom: 4.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark")), + children: [ + TextSpan( + text: title, + style: TextStyle( + fontWeight: isAction ? FontWeight.bold : FontWeight.normal, + color: isAction + ? MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark") + : MihColors.getPurpleColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + ), + ), + TextSpan(text: isAction ? ' $explanation' : ': $explanation'), + ], + ), + ), + ], + ), + ); + } + + Widget _buildTipPoint(String title, String explanation) { + return Padding( + padding: const EdgeInsets.only(left: 8.0, bottom: 4.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('• ', + style: TextStyle( + fontSize: 18, + color: MihColors.getBronze( + MzansiInnovationHub.of(context)!.theme.mode != "Dark"), + fontWeight: FontWeight.bold)), + Expanded( + child: RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16, + color: MihColors.getBronze( + MzansiInnovationHub.of(context)!.theme.mode == "Dark")), + children: [ + TextSpan( + text: title, + style: const TextStyle(fontWeight: FontWeight.bold)), + TextSpan(text: explanation), + ], + ), + ), + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + final Size size = MediaQuery.sizeOf(context); + final double width = size.width; + return MihPackageToolBody( + borderOn: false, + bodyItem: getBody(width), + ); + } + + Widget getBody(double width) { + return MihSingleChildScroll( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: Column( + children: [ + const Text( + 'Simple Rules and Strategy', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 30, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 8), + const Text( + 'Minesweeper is a puzzle game where you use numbers to figure out where the hidden bombs (mines) are located.', + style: TextStyle(fontSize: 16), + ), + // const Divider(height: 30), + const SizedBox(height: 15), + // --- 1. Two Main Actions --- + Container( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode != "Darl"), + borderRadius: BorderRadius.circular(15), + ), + child: Column( + children: [ + const SizedBox(height: 8), + _buildSectionTitle('1. Two Main Actions (Your Controls)'), + const SizedBox(height: 8), + _buildRulePoint( + title: 'Quick Tap (or Click): This is the Dig action.', + points: [ + 'Goal: To uncover a square and see a number clue.', + 'Risk: If you click a mine, the game ends!', + ], + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode != "Dark"), + ), + _buildRulePoint( + title: + 'Tap and Hold (or Long Press): This is the Flag action (🚩).', + points: [ + 'Goal: To safely mark a square that you are **certain** is a mine.', + 'Benefit: You cannot accidentally click a square that is flagged.', + ], + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode != "Dark"), + ), + const SizedBox(height: 4), + ], + ), + ), + const SizedBox(height: 15), + // --- 2. The Golden Rule: Reading the Numbers --- + Container( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode != "Darl"), + borderRadius: BorderRadius.circular(15), + ), + child: Column( + children: [ + const SizedBox(height: 8), + _buildSectionTitle('2. The Golden Rule: Reading the Numbers'), + const SizedBox(height: 8), + Text( + 'The number tells you exactly how many mines are touching that square (including sides and corners).', + style: TextStyle( + fontSize: 18, + fontStyle: FontStyle.italic, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Darl"), + ), + ), + const SizedBox(height: 8), + _buildNumberClue('Blank Space (a \'0\')', + 'Zero (0) mines are touching it. All surrounding squares are safe, and the game will open them for you automatically.'), + _buildNumberClue('\'1\'', + 'Only **one** mine is touching this square. You must find and flag that single mine.'), + _buildNumberClue('\'3\'', + 'Three mines are touching this square. You must find and flag all three.'), + const SizedBox(height: 4), + ], + ), + ), + const SizedBox(height: 15), + // --- 3. The Winning Strategy --- + Container( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode != "Darl"), + borderRadius: BorderRadius.circular(15), + ), + child: Column( + children: [ + const SizedBox(height: 8), + _buildSectionTitle( + '3. The Winning Strategy (The Deduction Loop)'), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Text( + 'The game is won by uncovering every single safe square and correctly flagging all the mines. Use this two-step loop to clear the board:', + style: TextStyle( + fontSize: 18, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Darl"), + ), + ), + ), + const SizedBox(height: 8), + _buildSubSectionTitle('A. Find the Mines (Where to Flag 🚩)'), + _buildStrategyPoint( + 'Look for a number that only has one choice for a mine.', + 'Example: If a \'1\' is touching only one hidden square, that hidden square **must** be the mine.'), + _buildStrategyPoint('Action:', + 'Tap and Hold to place a **Flag** on the square you are sure is a mine.', + isAction: true), + const SizedBox(height: 12), + _buildSubSectionTitle( + 'B. Find the Safe Squares (Where to Dig)'), + _buildStrategyPoint( + 'Look for a number that has been \'satisfied\' by your flags.', + 'Example: You see a \'2\'. You have already placed two 🚩 flags touching it. The \'2\' is satisfied.'), + _buildStrategyPoint('Action:', + 'Quick Tap any of the remaining hidden squares touching that \'satisfied\' number. They **must be safe** because the mine requirement has already been met.', + isAction: true), + ], + ), + ), + const SizedBox(height: 15), + // --- Key Beginner Tip --- + Container( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode != "Darl"), + borderRadius: BorderRadius.circular(15), + ), + child: Column( + children: [ + const SizedBox(height: 8), + _buildSectionTitle('✨ Key Beginner Tips'), + const SizedBox(height: 8), + _buildTipPoint('Start on the Edges and Corners:', + 'Numbers on the edge or corner of the board are easier to solve because they have fewer surrounding squares to check.'), + _buildTipPoint('Don\'t Guess:', + 'If you are down to two squares and either one could be the mine, look somewhere else on the board for a guaranteed, safe move.'), + const SizedBox(height: 8), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/Frontend/lib/mih_packages/mine_sweeper/package_tools/my_score_board.dart b/Frontend/lib/mih_packages/mine_sweeper/package_tools/my_score_board.dart new file mode 100644 index 00000000..7d8316b1 --- /dev/null +++ b/Frontend/lib/mih_packages/mine_sweeper/package_tools/my_score_board.dart @@ -0,0 +1,209 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:ken_logger/ken_logger.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/builders/build_my_scoreboard_list.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_minesweeper_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; + +class MyScoreBoard extends StatefulWidget { + const MyScoreBoard({super.key}); + + @override + State createState() => _MihMineSweeperLeaderBoardState(); +} + +class _MihMineSweeperLeaderBoardState extends State { + TextEditingController filterController = TextEditingController(); + + Future initialiseLeaderboard() async { + MzansiProfileProvider profileProvider = + context.read(); + MihMineSweeperProvider mineSweeperProvider = + context.read(); + filterController.text = mineSweeperProvider.difficulty; + KenLogger.success("getting data"); + await MihMinesweeperServices() + .getMyScoreboard(profileProvider, mineSweeperProvider); + KenLogger.success("${mineSweeperProvider.myScoreboard}"); + } + + void refreshLeaderBoard( + MihMineSweeperProvider mineSweeperProvider, String difficulty) { + mineSweeperProvider.setDifficulty(difficulty); + mineSweeperProvider.setLeaderboard(leaderboard: null); + mineSweeperProvider.setMyScoreboard(myScoreboard: null); + initialiseLeaderboard(); + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) async { + await initialiseLeaderboard(); + }); + } + + @override + Widget build(BuildContext context) { + final double width = MediaQuery.sizeOf(context).width; + return Consumer( + builder: (BuildContext context, + MihMineSweeperProvider mineSweeperProvider, Widget? child) { + return RefreshIndicator( + onRefresh: () async { + refreshLeaderBoard(mineSweeperProvider, filterController.text); + }, + child: MihPackageToolBody( + borderOn: false, + bodyItem: getBody(width), + ), + ); + }, + ); + } + + Widget getBody(double width) { + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + MihMineSweeperProvider mineSweeperProvider, Widget? child) { + if (mineSweeperProvider.myScoreboard == null) { + return Center( + child: Mihloadingcircle(), + ); + } else { + return SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Column( + children: [ + Center( + child: MihCircleAvatar( + imageFile: profileProvider.userProfilePicture, + width: 150, + editable: false, + fileNameController: null, + userSelectedfile: null, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onChange: (selectedImage) {}, + key: ValueKey(profileProvider.userProfilePicUrl), + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: MihDropdownField( + controller: filterController, + hintText: "Scoreboards", + dropdownOptions: const [ + "Very Easy", + "Easy", + "Intermediate", + "Hard", + ], + requiredText: true, + editable: true, + enableSearch: false, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + onSelected: (selection) { + refreshLeaderBoard(mineSweeperProvider, selection!); + }, + ), + ), + ], + ), + ), + const SizedBox(height: 10), + mineSweeperProvider.myScoreboard!.isEmpty + ? Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.mineSweeper, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + const SizedBox(height: 10), + Text( + "You have played and ${mineSweeperProvider.difficulty} yet.", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + const SizedBox(height: 25), + Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.normal, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + children: [ + TextSpan(text: "Press "), + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Icon( + FontAwesomeIcons.bomb, + size: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + TextSpan(text: " and start a new game"), + ], + ), + ), + ), + ], + ), + ) + : BuildMyScoreBoardList(), + ], + ), + ); + } + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_ai/mzansi_ai.dart b/Frontend/lib/mih_packages/mzansi_ai/mzansi_ai.dart index ccb43d38..1d694165 100644 --- a/Frontend/lib/mih_packages/mzansi_ai/mzansi_ai.dart +++ b/Frontend/lib/mih_packages/mzansi_ai/mzansi_ai.dart @@ -2,19 +2,14 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tools/ai_chat.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MzansiAi extends StatefulWidget { - // final AppUser signedInUser; - // final String? startUpQuestion; - final MzansiAiArguments arguments; const MzansiAi({ super.key, - required this.arguments, - // required this.signedInUser, - // this.startUpQuestion, }); @override @@ -22,16 +17,14 @@ class MzansiAi extends StatefulWidget { } class _MzansiAiState extends State { - int _selcetedIndex = 0; - MihPackageAction getAction() { return MihPackageAction( icon: const Icon(Icons.arrow_back), iconSize: 35, onTap: () { + context.read().setStartUpQuestion(null); context.goNamed( 'mihHome', - extra: widget.arguments.personalSelected, ); FocusScope.of(context).unfocus(); }, @@ -41,23 +34,18 @@ class _MzansiAiState extends State { MihPackageTools getTools() { Map temp = {}; temp[const Icon(Icons.chat)] = () { - setState(() { - _selcetedIndex = 0; - }); + context.read().setToolIndex(0); }; return MihPackageTools( tools: temp, - selcetedIndex: _selcetedIndex, + selcetedIndex: context.watch().toolIndex, ); } List getToolBody() { List toolBodies = [ - AiChat( - signedInUser: widget.arguments.signedInUser, - startUpQuestion: widget.arguments.startUpQuestion, - ), + AiChat(), ]; return toolBodies; } @@ -81,12 +69,9 @@ class _MzansiAiState extends State { appTools: getTools(), appBody: getToolBody(), appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, + selectedbodyIndex: context.watch().toolIndex, onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); - print("Index: $_selcetedIndex"); + context.read().setToolIndex(newValue); }, ); } diff --git a/Frontend/lib/mih_packages/mzansi_ai/package_tiles/mzansi_ai_tile.dart b/Frontend/lib/mih_packages/mzansi_ai/package_tiles/mzansi_ai_tile.dart index 24633b33..de331e7a 100644 --- a/Frontend/lib/mih_packages/mzansi_ai/package_tiles/mzansi_ai_tile.dart +++ b/Frontend/lib/mih_packages/mzansi_ai/package_tiles/mzansi_ai_tile.dart @@ -3,16 +3,13 @@ import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:flutter/material.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; class MzansiAiTile extends StatefulWidget { - final MzansiAiArguments arguments; final double packageSize; const MzansiAiTile({ super.key, - required this.arguments, required this.packageSize, }); @@ -27,7 +24,6 @@ class _MzansiAiTileState extends State { onTap: () { context.goNamed( 'mzansiAi', - extra: widget.arguments, ); // Navigator.of(context).pushNamed( // '/mzansi-ai', diff --git a/Frontend/lib/mih_packages/mzansi_ai/package_tools/ai_chat.dart b/Frontend/lib/mih_packages/mzansi_ai/package_tools/ai_chat.dart index 8f789669..c380456f 100644 --- a/Frontend/lib/mih_packages/mzansi_ai/package_tools/ai_chat.dart +++ b/Frontend/lib/mih_packages/mzansi_ai/package_tools/ai_chat.dart @@ -4,6 +4,8 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:gpt_markdown/gpt_markdown.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; @@ -14,22 +16,18 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_radio_options.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:flutter/material.dart'; import 'package:flutter_chat_ui/flutter_chat_ui.dart'; import 'package:flutter_chat_types/flutter_chat_types.dart' as types; import 'package:flutter/services.dart' show rootBundle; import 'package:flutter_tts/flutter_tts.dart'; import 'package:ollama_dart/ollama_dart.dart' as ollama; +import 'package:provider/provider.dart'; import 'package:uuid/uuid.dart'; class AiChat extends StatefulWidget { - final AppUser signedInUser; - final String? startUpQuestion; const AiChat({ super.key, - required this.signedInUser, - this.startUpQuestion, }); @override @@ -615,9 +613,13 @@ class _AiChatState extends State { @override void initState() { super.initState(); + MzansiAiProvider mzansiAiProvider = context.read(); + MzansiProfileProvider mzansiProfileProvider = + context.read(); _user = types.User( - firstName: widget.signedInUser.fname, - id: widget.signedInUser.app_id, //'82091008-a484-4a89-ae75-a22bf8d6f3ac', + firstName: mzansiProfileProvider.user!.fname, + id: mzansiProfileProvider + .user!.app_id, //'82091008-a484-4a89-ae75-a22bf8d6f3ac', ); _mihAI = types.User( firstName: "Mzansi AI", @@ -634,8 +636,10 @@ class _AiChatState extends State { ); initTTS(); _ttsVoiceController.addListener(voiceSelected); - if (widget.startUpQuestion != null && widget.startUpQuestion!.isNotEmpty) { - final partialText = types.PartialText(text: widget.startUpQuestion!); + if (mzansiAiProvider.startUpQuestion != null && + mzansiAiProvider.startUpQuestion!.isNotEmpty) { + final partialText = + types.PartialText(text: mzansiAiProvider.startUpQuestion!); WidgetsBinding.instance.addPostFrameCallback((_) { _handleSendPressed(partialText); }); diff --git a/Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart b/Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart index 9740c534..6d715696 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart @@ -1,20 +1,17 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:provider/provider.dart'; class BuildBusinessSearchResultsList extends StatefulWidget { final List businessList; - final String myLocation; - final String? startUpSearch; const BuildBusinessSearchResultsList({ super.key, required this.businessList, - required this.myLocation, - required this.startUpSearch, }); @override @@ -26,52 +23,48 @@ class _BuildBusinessSearchResultsListState extends State { @override Widget build(BuildContext context) { - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: widget.businessList.length, - separatorBuilder: (BuildContext context, index) { - return Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - }, - itemBuilder: (context, index) { - return Material( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - child: InkWell( - onTap: () { - context.goNamed( - 'businessProfileView', - extra: BusinessViewArguments( - widget.businessList[index], - widget.businessList[index].Name, + return Consumer( + builder: (BuildContext context, MzansiDirectoryProvider directoryProvider, + Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: widget.businessList.length, + separatorBuilder: (BuildContext context, index) { + return Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + itemBuilder: (context, index) { + return Material( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + child: InkWell( + onTap: () { + directoryProvider.setSelectedBusiness( + business: widget.businessList[index], + ); + context.pushNamed( + 'businessProfileView', + ); + }, + splashColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark") + .withOpacity(0.2), + borderRadius: BorderRadius.circular(15), + child: Padding( + padding: EdgeInsetsGeometry.symmetric( + // vertical: 5, + horizontal: 25, + ), + child: MihBusinessProfilePreview( + business: widget.businessList[index], + ), ), - ); - // // Navigator.of(context).pushNamed( - // // '/business-profile/view', - // // arguments: BusinessViewArguments( - // // widget.businessList[index], - // // widget.businessList[index].Name, - // // ), - // ); - }, - splashColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark") - .withOpacity(0.2), - borderRadius: BorderRadius.circular(15), - child: Padding( - padding: EdgeInsetsGeometry.symmetric( - // vertical: 5, - horizontal: 25, ), - child: MihBusinessProfilePreview( - business: widget.businessList[index], - myLocation: widget.myLocation, - ), - ), - ), + ); + }, ); }, ); diff --git a/Frontend/lib/mih_packages/mzansi_directory/builders/build_favourite_businesses_list.dart b/Frontend/lib/mih_packages/mzansi_directory/builders/build_favourite_businesses_list.dart index 1c2509fa..8f4e638d 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/builders/build_favourite_businesses_list.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/builders/build_favourite_businesses_list.dart @@ -1,18 +1,17 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:provider/provider.dart'; class BuildFavouriteBusinessesList extends StatefulWidget { final List favouriteBusinesses; - final String? myLocation; const BuildFavouriteBusinessesList({ super.key, required this.favouriteBusinesses, - required this.myLocation, }); @override @@ -24,54 +23,49 @@ class _BuildFavouriteBusinessesListState extends State { @override Widget build(BuildContext context) { - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: widget.favouriteBusinesses.length, - separatorBuilder: (BuildContext context, index) { - return Divider( - color: Theme.of(context).colorScheme.secondary, - ); - }, - itemBuilder: (context, index) { - final Business? business = widget.favouriteBusinesses[index]; - - if (business == null) { - return const SizedBox(); // Or a placeholder if a business couldn't be loaded - } - - return Material( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - child: InkWell( - onTap: () { - context.goNamed( - 'businessProfileView', - extra: BusinessViewArguments( - widget.favouriteBusinesses[index]!, - widget.favouriteBusinesses[index]!.Name, + return Consumer( + builder: (BuildContext context, MzansiDirectoryProvider directoryProvider, + Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: widget.favouriteBusinesses.length, + separatorBuilder: (BuildContext context, index) { + return Divider( + color: Theme.of(context).colorScheme.secondary, + ); + }, + itemBuilder: (context, index) { + if (widget.favouriteBusinesses[index] == null) { + return const SizedBox(); // Or a placeholder if a business couldn't be loaded + } + return Material( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + child: InkWell( + onTap: () { + directoryProvider.setSelectedBusiness( + business: widget.favouriteBusinesses[index]!, + ); + context.goNamed( + 'businessProfileView', + ); + }, + splashColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark") + .withOpacity(0.2), + borderRadius: BorderRadius.circular(15), + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: 25, + ), + child: MihBusinessProfilePreview( + business: widget.favouriteBusinesses[index]!, + ), ), - ); - // Navigator.of(context).pushNamed( - // '/business-profile/view', - // arguments: BusinessViewArguments( - // business, - // business.Name, - // ), - // ); - }, - splashColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark") - .withOpacity(0.2), - borderRadius: BorderRadius.circular(15), - child: Padding( - padding: EdgeInsets.symmetric( - horizontal: 25, ), - child: MihBusinessProfilePreview( - business: business, myLocation: widget.myLocation), - ), - ), + ); + }, ); }, ); diff --git a/Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart b/Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart index 8135ce94..bebd0521 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart @@ -3,7 +3,9 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_personal_profile_preview.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:provider/provider.dart'; class BuildUserSearchResultsList extends StatefulWidget { final List userList; @@ -21,45 +23,46 @@ class _BuildUserSearchResultsListState extends State { @override Widget build(BuildContext context) { - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - itemCount: widget.userList.length, - separatorBuilder: (BuildContext context, index) { - return Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - }, - itemBuilder: (context, index) { - return Material( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - child: InkWell( - onTap: () { - context.goNamed( - 'mzansiProfileView', - extra: widget.userList[index], - ); - // Navigator.of(context).pushNamed( - // '/mzansi-profile/view', - // arguments: widget.userList[index], - // ); - }, - splashColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark") - .withOpacity(0.2), - borderRadius: BorderRadius.circular(15), - child: Padding( - padding: EdgeInsetsGeometry.symmetric( - // vertical: 5, - horizontal: 25, + return Consumer( + builder: (BuildContext context, MzansiDirectoryProvider directoryProvider, + Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: widget.userList.length, + separatorBuilder: (BuildContext context, index) { + return Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + itemBuilder: (context, index) { + return Material( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + child: InkWell( + onTap: () { + directoryProvider.setSelectedUser( + user: widget.userList[index]); + context.pushNamed( + 'mzansiProfileView', + ); + }, + splashColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark") + .withOpacity(0.2), + borderRadius: BorderRadius.circular(15), + child: Padding( + padding: EdgeInsetsGeometry.symmetric( + // vertical: 5, + horizontal: 25, + ), + child: + MihPersonalProfilePreview(user: widget.userList[index]), + ), ), - child: MihPersonalProfilePreview( - user: widget.userList[index], - ), - ), - ), + ); + }, ); }, ); diff --git a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart index eb390b29..baa1dda3 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart @@ -1,19 +1,18 @@ import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:go_router/go_router.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; +import 'package:provider/provider.dart'; class MzansiDirectory extends StatefulWidget { - final MzansiDirectoryArguments arguments; const MzansiDirectory({ super.key, - required this.arguments, }); @override @@ -21,75 +20,56 @@ class MzansiDirectory extends StatefulWidget { } class _MzansiDirectoryState extends State { - int _selcetedIndex = 0; late Future futurePosition = MIHLocationAPI().getGPSPosition(context); + Future initialiseGPSLocation() async { + MzansiDirectoryProvider directoryProvider = + context.read(); + MIHLocationAPI().getGPSPosition(context).then((position) { + directoryProvider.setUserPosition(position); + }); + } + @override void initState() { super.initState(); - if (widget.arguments.packageIndex == null) { - _selcetedIndex = 0; - } else { - _selcetedIndex = widget.arguments.packageIndex!; - } + WidgetsBinding.instance.addPostFrameCallback((_) async { + initialiseGPSLocation(); + }); } @override Widget build(BuildContext context) { - print('MzansiDirectory build method called!'); return MihPackage( appActionButton: getAction(), appTools: getTools(), appBody: getToolBody(), appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, + selectedbodyIndex: context.watch().toolIndex, onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); + context.read().setToolIndex(newValue); }, ); } List getToolBody() { - List toolBodies = [ - FutureBuilder( - future: futurePosition, - builder: (context, asyncSnapshot) { - String myLocation = ""; - if (asyncSnapshot.connectionState == ConnectionState.waiting) { - myLocation = "Getting Your GPS Location Ready"; - } else { - myLocation = asyncSnapshot.data - .toString() - .replaceAll("Latitude: ", "") - .replaceAll("Longitude: ", ""); - } - return MihSearchMzansi( - personalSearch: widget.arguments.personalSearch, - myLocation: myLocation, - startSearchText: widget.arguments.startSearchText, - ); - }), + List toolBodies = []; + // String myLocation = "Getting Your GPS Location Ready"; + // if (directoryProvider.userPosition != null) { + // myLocation = directoryProvider.userPosition + // .toString() + // .replaceAll("Latitude: ", "") + // .replaceAll("Longitude: ", ""); + // } + toolBodies.addAll([ + MihSearchMzansi( + // personalSearch: directoryProvider.personalSearch, + // startSearchText: "", + ), // MihContacts(), - FutureBuilder( - future: futurePosition, - builder: (context, asyncSnapshot) { - String myLocation = ""; - if (asyncSnapshot.connectionState == ConnectionState.waiting) { - myLocation = "Getting Your GPS Location Ready"; - } else { - myLocation = asyncSnapshot.data - .toString() - .replaceAll("Latitude: ", "") - .replaceAll("Longitude: ", ""); - } - return MihFavouriteBusinesses( - myLocation: myLocation, - ); - }), - ]; + MihFavouriteBusinesses(), + ]); return toolBodies; } @@ -98,10 +78,13 @@ class _MzansiDirectoryState extends State { icon: const Icon(Icons.arrow_back), iconSize: 35, onTap: () { + MzansiDirectoryProvider directoryProvider = + context.read(); context.goNamed( 'mihHome', - extra: widget.arguments.personalSearch, ); + directoryProvider.setToolIndex(0); + directoryProvider.setPersonalSearch(true); FocusScope.of(context).unfocus(); }, ); @@ -110,23 +93,14 @@ class _MzansiDirectoryState extends State { MihPackageTools getTools() { Map temp = {}; temp[const Icon(Icons.search)] = () { - setState(() { - _selcetedIndex = 0; - }); + context.read().setToolIndex(0); }; - // temp[const Icon(Icons.person)] = () { - // setState(() { - // _selcetedIndex = 1; - // }); - // }; temp[const Icon(Icons.business_center)] = () { - setState(() { - _selcetedIndex = 1; - }); + context.read().setToolIndex(1); }; return MihPackageTools( tools: temp, - selcetedIndex: _selcetedIndex, + selcetedIndex: context.watch().toolIndex, ); } @@ -134,7 +108,7 @@ class _MzansiDirectoryState extends State { List toolTitles = [ "Mzansi Search", "Favourite Businesses", - "Contacts", + // "Contacts", ]; return toolTitles; } diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart index ee72ba50..10dfa6ac 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart @@ -1,18 +1,15 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; class MzansiDirectoryTile extends StatefulWidget { final double packageSize; - final bool personalSelected; const MzansiDirectoryTile({ super.key, required this.packageSize, - required this.personalSelected, }); @override @@ -26,10 +23,6 @@ class _MzansiDirectoryTileState extends State { onTap: () { context.goNamed( "mzansiDirectory", - extra: MzansiDirectoryArguments( - personalSearch: widget.personalSelected, - startSearchText: null, - ), ); // Navigator.of(context).pushNamed( // '/mzansi-directory', diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart index 6c8898ca..eeb53ba0 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart @@ -1,24 +1,22 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_favourite_businesses_list.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart'; -import 'package:supertokens_flutter/supertokens.dart'; +import 'package:provider/provider.dart'; class MihFavouriteBusinesses extends StatefulWidget { - final String? myLocation; const MihFavouriteBusinesses({ super.key, - required this.myLocation, }); @override @@ -29,42 +27,42 @@ class _MihFavouriteBusinessesState extends State { final TextEditingController businessSearchController = TextEditingController(); final FocusNode searchFocusNode = FocusNode(); - late Future> boookmarkedBusinessListFuture; - List listBookmarkedBusinesses = []; final ValueNotifier> searchBookmarkedBusinesses = ValueNotifier([]); - late Future> businessDetailsMapFuture; - Map _businessDetailsMap = {}; Timer? _debounce; - Future> - getAndMapAllBusinessDetailsForBookmarkedBusinesses() async { - String user_id = await SuperTokens.getUserId(); - List bookmarked = await MihMzansiDirectoryServices() - .getAllUserBookmarkedBusiness(user_id); - listBookmarkedBusinesses = bookmarked; + Future getAndMapAllBusinessDetailsForBookmarkedBusinesses( + MzansiProfileProvider mzansiProfileProvider, + MzansiDirectoryProvider directoryProvider, + ) async { + await MihMzansiDirectoryServices().getAllUserBookmarkedBusiness( + mzansiProfileProvider.user!.app_id, + directoryProvider, + ); Map businessMap = {}; List> detailFutures = []; - for (var item in bookmarked) { + for (var item in directoryProvider.bookmarkedBusinesses) { detailFutures.add(MihBusinessDetailsServices() .getBusinessDetailsByBusinessId(item.business_id)); } List details = await Future.wait(detailFutures); - for (int i = 0; i < bookmarked.length; i++) { - businessMap[bookmarked[i].business_id] = details[i]; + for (int i = 0; i < directoryProvider.bookmarkedBusinesses.length; i++) { + businessMap[directoryProvider.bookmarkedBusinesses[i].business_id] = + details[i]; } - _businessDetailsMap = businessMap; - _filterAndSetBusinesses(); - return businessMap; + directoryProvider.setBusinessDetailsMap(detailsMap: businessMap); + _filterAndSetBusinesses(directoryProvider); } - void _filterAndSetBusinesses() { + void _filterAndSetBusinesses(MzansiDirectoryProvider directoryProvider) { List businessesToDisplay = []; String query = businessSearchController.text.toLowerCase(); - for (var bookmarked in listBookmarkedBusinesses) { + for (var bookmarked in directoryProvider.bookmarkedBusinesses) { if (bookmarked.business_name.toLowerCase().contains(query)) { - if (_businessDetailsMap.containsKey(bookmarked.business_id)) { - businessesToDisplay.add(_businessDetailsMap[bookmarked.business_id]); + if (directoryProvider.businessDetailsMap + .containsKey(bookmarked.business_id)) { + businessesToDisplay.add( + directoryProvider.businessDetailsMap[bookmarked.business_id]); } } } @@ -82,14 +80,21 @@ class _MihFavouriteBusinessesState extends State { @override void initState() { super.initState(); - businessDetailsMapFuture = - getAndMapAllBusinessDetailsForBookmarkedBusinesses(); + MzansiDirectoryProvider directoryProvider = + context.read(); + MzansiProfileProvider mzansiProfileProvider = + context.read(); + + getAndMapAllBusinessDetailsForBookmarkedBusinesses( + mzansiProfileProvider, + directoryProvider, + ); businessSearchController.addListener(() { if (_debounce?.isActive ?? false) { _debounce!.cancel(); } _debounce = Timer(const Duration(milliseconds: 200), () { - _filterAndSetBusinesses(); + _filterAndSetBusinesses(directoryProvider); }); }); } @@ -123,141 +128,95 @@ class _MihFavouriteBusinessesState extends State { ), ), const SizedBox(height: 10), - FutureBuilder>( - future: businessDetailsMapFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return Mihloadingcircle( - message: "Getting your favourites", + ValueListenableBuilder>( + valueListenable: searchBookmarkedBusinesses, + builder: (context, filteredBusinesses, child) { + if (filteredBusinesses.isEmpty && + businessSearchController.text.isNotEmpty) { + return Column( + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.iDontKnow, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + const SizedBox(height: 10), + Text( + "Let's try refining your search", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ], ); - } else if (snapshot.connectionState == ConnectionState.done) { - if (snapshot.hasData && snapshot.data!.isNotEmpty) { - // No need to re-filter here, _filterAndSetBusinesses is called in initState - // and by the text controller listener. - return ValueListenableBuilder>( - valueListenable: - searchBookmarkedBusinesses, // Listen to changes in this - builder: (context, businesses, child) { - // Display message if no results after search - if (businesses.isEmpty && - businessSearchController.text.isNotEmpty) { - return Column( - children: [ - const SizedBox(height: 50), - Icon( - MihIcons.iDontKnow, - size: 165, + } else if (filteredBusinesses.isEmpty && + businessSearchController.text.isEmpty) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.businessProfile, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + const SizedBox(height: 10), + Text( + "No favourite businesses added to your mzansi directory", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + const SizedBox(height: 25), + Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.normal, color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)! .theme .mode == "Dark"), ), - const SizedBox(height: 10), - Text( - "Let's try refining your search", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - ), - ), - ], - ); - } - return BuildFavouriteBusinessesList( - favouriteBusinesses: - businesses, // Pass the filtered list from ValueNotifier - myLocation: widget.myLocation, - ); - }, - ); - } else { - // This block handles the case where there are no bookmarked businesses initially - - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 50), - Icon( - MihIcons.businessProfile, - size: 165, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - const SizedBox(height: 10), - Text( - "No favourite businesses added to your mzansi directory", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), + children: [ + TextSpan(text: "Use the mzansi search"), + TextSpan( + text: + " to find your favourite businesses of mzansi"), + ], ), ), - const SizedBox(height: 25), - Center( - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.normal, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - ), - children: [ - TextSpan(text: "Use the mzansi search"), - // WidgetSpan( - // alignment: - // PlaceholderAlignment.middle, - // child: Icon( - // Icons.search, - // size: 20, - // color: - // MzansiInnovationHub.of(context)! - // .theme - // .secondaryColor(), - // ), - // ), - TextSpan( - text: - " to find your favourite businesses of mzansi"), - ], - ), - ), - ), - ], - ), - ); - } - } else if (snapshot.hasError) { - return Center( - child: Text( - "Error loading bookmarked businesses: ${snapshot.error}"), // Show specific error - ); - } else { - // Fallback for unexpected states - return Center( - child: Text("An unknown error occurred."), + ), + ], + ), ); } + return BuildFavouriteBusinessesList( + favouriteBusinesses: filteredBusinesses, + ); }), ], ), diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart index 73cfc4bb..472a67db 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; @@ -9,22 +10,19 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; +import 'package:provider/provider.dart'; class MihSearchMzansi extends StatefulWidget { - final bool personalSearch; - final String? myLocation; - final String? startSearchText; const MihSearchMzansi({ super.key, - required this.personalSearch, - required this.myLocation, - required this.startSearchText, }); @override @@ -35,80 +33,89 @@ class _MihSearchMzansiState extends State { final TextEditingController mzansiSearchController = TextEditingController(); final TextEditingController businessTypeController = TextEditingController(); final FocusNode searchFocusNode = FocusNode(); - late bool userSearch; - Future?> futureUserSearchResults = Future.value(); - Future?> futureBusinessSearchResults = Future.value(); + // late bool userSearch; + // Future?> futureUserSearchResults = Future.value(); List userSearchResults = []; List businessSearchResults = []; late Future> availableBusinessTypes; bool filterOn = false; + bool loadingSearchResults = false; - void swapPressed() { + Future swapPressed(MzansiProfileProvider profileProvider, + MzansiDirectoryProvider directoryProvider) async { + directoryProvider.setPersonalSearch(!directoryProvider.personalSearch); setState(() { - userSearch = !userSearch; if (filterOn) { filterOn = !filterOn; } }); if (businessTypeController.text.isNotEmpty) { setState(() { - futureBusinessSearchResults = Future.value(); businessTypeController.clear(); }); } - searchPressed(); + await searchPressed(profileProvider, directoryProvider); } - void clearAll() { + void clearAll(MzansiDirectoryProvider directoryProvider) { + directoryProvider.setSearchedBusinesses(searchedBusinesses: []); + directoryProvider.setSearchedUsers(searchedUsers: []); + directoryProvider.setSearchTerm(searchTerm: ""); setState(() { - futureUserSearchResults = Future.value(); - futureBusinessSearchResults = Future.value(); mzansiSearchController.clear(); businessTypeController.clear(); }); } - void searchPressed() { + Future searchPressed(MzansiProfileProvider profileProvider, + MzansiDirectoryProvider directoryProvider) async { setState(() { - // userSearch = !userSearch; - if (userSearch && mzansiSearchController.text.isNotEmpty) { - futureUserSearchResults = - MihUserServices().searchUsers(mzansiSearchController.text, context); - } else { - if ( - // mzansiSearchController.text.isNotEmpty && - businessTypeController.text.isNotEmpty) { - futureBusinessSearchResults = MihBusinessDetailsServices() - .searchBusinesses(mzansiSearchController.text, - businessTypeController.text, context); - } else if (mzansiSearchController.text.isNotEmpty) { - futureBusinessSearchResults = MihBusinessDetailsServices() - .searchBusinesses(mzansiSearchController.text, - businessTypeController.text, context); - } + loadingSearchResults = true; + }); + directoryProvider.setSearchTerm(searchTerm: mzansiSearchController.text); + directoryProvider.setBusinessTypeFilter( + businessTypeFilter: businessTypeController.text); + if (directoryProvider.personalSearch && + directoryProvider.searchTerm.isNotEmpty) { + final userResults = await MihUserServices() + .searchUsers(profileProvider, directoryProvider.searchTerm, context); + directoryProvider.setSearchedUsers(searchedUsers: userResults); + } else { + List? businessSearchResults = []; + if (directoryProvider.businessTypeFilter.isNotEmpty) { + businessSearchResults = await MihBusinessDetailsServices() + .searchBusinesses(directoryProvider.searchTerm, + directoryProvider.businessTypeFilter, context); + } else if (directoryProvider.searchTerm.isNotEmpty) { + businessSearchResults = await MihBusinessDetailsServices() + .searchBusinesses(directoryProvider.searchTerm, + directoryProvider.businessTypeFilter, context); } + directoryProvider.setSearchedBusinesses( + searchedBusinesses: businessSearchResults); + } + setState(() { + loadingSearchResults = false; }); } @override void dispose() { super.dispose(); + businessTypeController.dispose(); mzansiSearchController.dispose(); } @override void initState() { super.initState(); - setState(() { - userSearch = widget.personalSearch; - availableBusinessTypes = - MihBusinessDetailsServices().fetchAllBusinessTypes(); - if (widget.startSearchText != null) { - mzansiSearchController.text = widget.startSearchText!; - searchPressed(); - } else { - mzansiSearchController.text = ""; - } + MzansiDirectoryProvider directoryProvider = + context.read(); + availableBusinessTypes = + MihBusinessDetailsServices().fetchAllBusinessTypes(); + mzansiSearchController.text = ""; + WidgetsBinding.instance.addPostFrameCallback((_) async { + directoryProvider.setSearchedUsers(searchedUsers: []); }); } @@ -123,444 +130,427 @@ class _MihSearchMzansiState extends State { } Widget getBody(double width) { - return MihSingleChildScroll( - child: Column( - children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: width / 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: MihSearchBar( - controller: mzansiSearchController, - hintText: "Search Mzansi", - prefixIcon: Icons.search, - prefixAltIcon: userSearch ? Icons.person : Icons.business, - suffixTools: [ - IconButton( - onPressed: () { - swapPressed(); - }, - icon: Icon( - Icons.swap_horiz_rounded, - size: 35, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - ], - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - hintColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onPrefixIconTap: () { - searchPressed(); - }, - onClearIconTap: () { - clearAll(); - }, - searchFocusNode: searchFocusNode, - ), - ), - Visibility( - visible: !userSearch, - child: const SizedBox(width: 10), - ), - Visibility( - visible: !userSearch, - child: IconButton( - onPressed: () { - if (filterOn) { - clearAll(); - } - setState(() { - filterOn = !filterOn; - }); - }, - icon: Icon( - !filterOn - ? Icons.filter_list_rounded - : Icons.filter_list_off_rounded, - size: 35, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - ), - ], - ), - ), - const SizedBox(height: 10), - FutureBuilder( - future: availableBusinessTypes, - builder: (context, asyncSnapshot) { - List options = []; - if (asyncSnapshot.connectionState == ConnectionState.done) { - options.addAll(asyncSnapshot.data!); - } - return Visibility( - visible: filterOn, - child: Padding( - padding: EdgeInsets.symmetric(horizontal: width / 20), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: MihDropdownField( - controller: businessTypeController, - hintText: "Business Type", - dropdownOptions: options, - requiredText: true, - editable: true, - enableSearch: true, - ), - ), - const SizedBox(width: 10), - MihButton( - onPressed: () { - if (businessTypeController.text.isNotEmpty) { - searchPressed(); - } else { - MihAlertServices().errorAlert( - "Business Type Not Selected", - "Please ensure you have selected a Business Type before seareching for Businesses of Mzansi", - context, - ); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - elevation: 10, - child: Text( - "Search", - style: TextStyle( + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + MzansiDirectoryProvider directoryProvider, Widget? child) { + return MihSingleChildScroll( + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: MihSearchBar( + controller: mzansiSearchController, + hintText: "Search Mzansi", + prefixIcon: Icons.search, + prefixAltIcon: directoryProvider.personalSearch + ? Icons.person + : Icons.business, + suffixTools: [ + IconButton( + onPressed: () { + swapPressed(profileProvider, directoryProvider); + }, + icon: Icon( + Icons.swap_horiz_rounded, + size: 35, color: MihColors.getPrimaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, ), ), - ), - ], + ], + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + hintColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onPrefixIconTap: () { + searchPressed(profileProvider, directoryProvider); + }, + onClearIconTap: () { + clearAll(directoryProvider); + }, + searchFocusNode: searchFocusNode, + ), ), - ), - ); - }), - const SizedBox(height: 10), - displaySearchResults(userSearch, widget.myLocation ?? ""), - ], - ), + Visibility( + visible: !directoryProvider.personalSearch, + child: const SizedBox(width: 10), + ), + Visibility( + visible: !directoryProvider.personalSearch, + child: IconButton( + onPressed: () { + if (filterOn) { + clearAll(directoryProvider); + } + setState(() { + filterOn = !filterOn; + }); + }, + icon: Icon( + !filterOn + ? Icons.filter_list_rounded + : Icons.filter_list_off_rounded, + size: 35, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + ], + ), + ), + const SizedBox(height: 10), + FutureBuilder( + future: availableBusinessTypes, + builder: (context, asyncSnapshot) { + List options = []; + if (asyncSnapshot.connectionState == ConnectionState.done) { + options.addAll(asyncSnapshot.data!); + } + return Visibility( + visible: filterOn, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: MihDropdownField( + controller: businessTypeController, + hintText: "Business Type", + dropdownOptions: options, + requiredText: true, + editable: true, + enableSearch: true, + ), + ), + const SizedBox(width: 10), + MihButton( + onPressed: () { + if (businessTypeController.text.isNotEmpty) { + searchPressed( + profileProvider, directoryProvider); + } else { + MihAlertServices().errorAlert( + "Business Type Not Selected", + "Please ensure you have selected a Business Type before seareching for Businesses of Mzansi", + context, + ); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + elevation: 10, + child: Text( + "Search", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ), + ); + }), + const SizedBox(height: 10), + displaySearchResults(directoryProvider), + ], + ), + ); + }, ); } - Widget displaySearchResults(bool userSearch, String myLocation) { - if (userSearch) { - return FutureBuilder( - future: futureUserSearchResults, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Mihloadingcircle(); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData && - snapshot.requireData!.isNotEmpty) { - // return Text("Pulled Data successfully"); - snapshot.requireData! - .sort((a, b) => a.username.compareTo(b.username)); - return Column( - children: [ - Text( - "People of Mzansi", - style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 10), - BuildUserSearchResultsList(userList: snapshot.requireData!), - ], - ); - } else if (!snapshot.hasData) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 50), - Icon( - MihIcons.personalProfile, - size: 165, + Widget displayBusinessSearchResults( + MzansiDirectoryProvider directoryProvider) { + KenLogger.success( + "Searched Businesses: ${directoryProvider.searchedBusinesses}"); + if (directoryProvider.searchedBusinesses == null || loadingSearchResults) { + return Center( + child: const Mihloadingcircle(), + ); + } else if (directoryProvider.searchedBusinesses!.isNotEmpty) { + // return Text("Pulled Data successfully"); + directoryProvider.searchedBusinesses! + .sort((a, b) => a.Name.compareTo(b.Name)); + return Column( + children: [ + Text( + "Businesses of Mzansi", + style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + BuildBusinessSearchResultsList( + businessList: directoryProvider.searchedBusinesses!, + ), + ], + ); + } else if (directoryProvider.searchedBusinesses!.isEmpty && + directoryProvider.searchTerm.isNotEmpty) { + // return Text("Pulled Data successfully"); + return Column( + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.iDontKnow, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + const SizedBox(height: 25), + Text( + "Let's try refining your search", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + ], + ); + } else if (directoryProvider.searchedBusinesses!.isEmpty && + directoryProvider.searchTerm.isEmpty) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.businessProfile, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + const SizedBox(height: 10), + Text( + "Search for businesses of Mzansi!", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + const SizedBox(height: 25), + Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.normal, color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), - const SizedBox(height: 10), - Text( - "Search for people of Mzansi!", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - const SizedBox(height: 25), - Center( - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.normal, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - children: [ - TextSpan(text: "Press "), - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Icon( - Icons.swap_horiz_rounded, - size: 20, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - TextSpan(text: " to search for businesses of Mzansi"), - ], + children: [ + TextSpan(text: "Press "), + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Icon( + Icons.swap_horiz_rounded, + size: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), ), ), - ), - ], - ), - ); - // return Column( - // mainAxisAlignment: MainAxisAlignment.center, - // crossAxisAlignment: CrossAxisAlignment.center, - // children: [ - // const SizedBox(height: 50), - // Icon( - // MihIcons.personalProfile, - // size: 165, - // color: - // MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // const SizedBox(height: 10), - // Text( - // "People Of Mzansi!", - // textAlign: TextAlign.center, - // overflow: TextOverflow.visible, - // style: TextStyle( - // fontSize: 25, - // fontWeight: FontWeight.bold, - // color: - // MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // ), - // ], - // ); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData && - snapshot.requireData!.isEmpty) { - // return Text("Pulled Data successfully"); - return Column( - children: [ - const SizedBox(height: 50), - Icon( - MihIcons.iDontKnow, - size: 165, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + TextSpan(text: " to search for people of Mzansi"), + ], ), - const SizedBox(height: 10), - Text( - "Let's try refining your search", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, + ), + ), + const SizedBox(height: 10), + Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, + fontSize: 20, + fontWeight: FontWeight.normal, color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), + children: [ + TextSpan(text: "Press "), + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Icon( + Icons.filter_list_rounded, + size: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + TextSpan(text: " to filter business types"), + ], ), - ], - ); - } else { - return Center( - child: Text( - "Error pulling Patients Data\n/users/search/${mzansiSearchController.text}", - style: TextStyle( - fontSize: 25, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark")), - textAlign: TextAlign.center, ), - ); - } - }, + ), + ], + ), ); } else { - return FutureBuilder( - future: futureBusinessSearchResults, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Mihloadingcircle(); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData && - snapshot.requireData!.isNotEmpty) { - // return Text("Pulled Data successfully"); - snapshot.requireData!.sort((a, b) => a.Name.compareTo(b.Name)); - return Column( - children: [ - Text( - "Businesses of Mzansi", - style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), - ), - const SizedBox(height: 10), - BuildBusinessSearchResultsList( - businessList: snapshot.requireData!, - myLocation: myLocation, - startUpSearch: mzansiSearchController.text, - ), - ], - ); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData && - snapshot.requireData!.isEmpty) { - // return Text("Pulled Data successfully"); - return Column( - children: [ - const SizedBox(height: 50), - Icon( - MihIcons.iDontKnow, - size: 165, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - const SizedBox(height: 25), - Text( - "Let's try refining your search", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - ], - ); - } else if (!snapshot.hasData) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 50), - Icon( - MihIcons.businessProfile, - size: 165, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - const SizedBox(height: 10), - Text( - "Search for businesses of Mzansi!", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - const SizedBox(height: 25), - Center( - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.normal, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - children: [ - TextSpan(text: "Press "), - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Icon( - Icons.swap_horiz_rounded, - size: 20, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - TextSpan(text: " to search for people of Mzansi"), - ], - ), - ), - ), - const SizedBox(height: 10), - Center( - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.normal, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - children: [ - TextSpan(text: "Press "), - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Icon( - Icons.filter_list_rounded, - size: 20, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - TextSpan(text: " to filter business types"), - ], - ), - ), - ), - ], - ), - ); - } else { - return Center( - child: Text( - "Error pulling Patients Data\n/users/search/${mzansiSearchController.text}", - style: TextStyle( - fontSize: 25, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark")), - textAlign: TextAlign.center, - ), - ); - } - }, + return Center( + child: Text( + "Error pulling Patients Data\n/users/search/${directoryProvider.searchTerm}", + style: TextStyle( + fontSize: 25, + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark")), + textAlign: TextAlign.center, + ), ); } } + + Widget displayPersonalSearchResults( + MzansiDirectoryProvider directoryProvider) { + if (directoryProvider.searchedUsers == null || loadingSearchResults) { + return Center( + child: const Mihloadingcircle(), + ); + } else if (directoryProvider.searchedUsers!.isNotEmpty) { + // return Text("Pulled Data successfully"); + directoryProvider.searchedUsers! + .sort((a, b) => a.username.compareTo(b.username)); + return Column( + children: [ + Text( + "People of Mzansi", + style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + BuildUserSearchResultsList( + userList: directoryProvider.searchedUsers!), + ], + ); + } else if (directoryProvider.searchedUsers!.isEmpty && + directoryProvider.searchTerm.isEmpty) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.personalProfile, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + const SizedBox(height: 10), + Text( + "Search for people of Mzansi!", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + const SizedBox(height: 25), + Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.normal, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + children: [ + TextSpan(text: "Press "), + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Icon( + Icons.swap_horiz_rounded, + size: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + TextSpan(text: " to search for businesses of Mzansi"), + ], + ), + ), + ), + ], + ), + ); + } else if (directoryProvider.searchedUsers!.isEmpty && + directoryProvider.searchTerm.isNotEmpty) { + return Column( + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.iDontKnow, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + const SizedBox(height: 10), + Text( + "Let's try refining your search", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + ], + ); + } else { + return Center( + child: Text( + "Error pulling Patients Data\n/users/search/${directoryProvider.searchTerm}", + style: TextStyle( + fontSize: 25, + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark")), + textAlign: TextAlign.center, + ), + ); + } + } + + Widget displaySearchResults(MzansiDirectoryProvider directoryProvider) { + if (directoryProvider.personalSearch) { + return displayPersonalSearchResults(directoryProvider); + } else { + return displayBusinessSearchResults(directoryProvider); + } + } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_employee_list.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_employee_list.dart index edc2b570..fa7fe96a 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_employee_list.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_employee_list.dart @@ -1,34 +1,15 @@ -import 'dart:convert'; - -import 'package:flutter_speed_dial/flutter_speed_dial.dart'; -import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart'; -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_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_edit_employee_details_window.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:flutter/material.dart'; -import 'package:supertokens_flutter/http.dart' as http; +import 'package:provider/provider.dart'; class BuildEmployeeList extends StatefulWidget { - final List employees; - final BusinessArguments arguments; - const BuildEmployeeList({ super.key, - required this.employees, - required this.arguments, }); @override @@ -36,369 +17,57 @@ class BuildEmployeeList extends StatefulWidget { } class _BuildEmployeeListState extends State { - TextEditingController accessController = TextEditingController(); - TextEditingController typeController = TextEditingController(); - TextEditingController fnameController = TextEditingController(); - TextEditingController lnameController = TextEditingController(); - - final _formKey = GlobalKey(); final baseAPI = AppEnviroment.baseApiUrl; - Future updateEmployeeAPICall(int index) async { - showDialog( - context: context, - builder: (context) { - return const Mihloadingcircle(); - }, - ); - - var response = await http.put( - Uri.parse("$baseAPI/business-user/employees/update/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "business_id": widget.employees[index].business_id, - "app_id": widget.employees[index].app_id, - "title": typeController.text, - "access": accessController.text, - }), - ); - if (response.statusCode == 200) { - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // //setState(() {}); - // Navigator.of(context).pushNamed( - // '/business-profile/manage', - // arguments: BusinessArguments( - // widget.arguments.signedInUser, - // widget.arguments.businessUser, - // widget.arguments.business, - // ), - // ); - String message = "Your employees details have been updated."; - successPopUp(message, false); - } else { - internetConnectionPopUp(); - } - } - - Future deleteNoteApiCall(int index) async { - var response = await http.delete( - Uri.parse("$baseAPI/business-user/employees/delete/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "business_id": widget.employees[index].business_id, - "app_id": widget.employees[index].app_id, - }), - ); - //print("Here4"); - //print(response.statusCode); - if (response.statusCode == 200) { - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pushNamed( - // '/business-profile/manage', - // arguments: BusinessArguments( - // widget.arguments.signedInUser, - // widget.arguments.businessUser, - // widget.arguments.business, - // ), - // ); - String message = - "The employee has been deleted successfully. This means they will no longer have access to your business profile"; - successPopUp(message, false); - } else { - internetConnectionPopUp(); - } - } - - void successPopUp(String message, bool stayOnPersonalSide) { - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.check_circle_outline_rounded, - size: 150, - color: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: "Successfully Updated Profile", - alertBody: Column( - children: [ - Text( - message, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 15, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 25), - Center( - child: MihButton( - onPressed: () { - context.goNamed( - 'mihHome', - extra: stayOnPersonalSide, - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - elevation: 10, - width: 300, - child: Text( - "Dismiss", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ) - ], - ), - alertColour: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - // return MIHSuccessMessage( - // successType: "Success", - // successMessage: message, - // ); - }, - ); - } - - void internetConnectionPopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); - } - - bool isRequiredFieldsCaptured() { - if (accessController.text.isEmpty || typeController.text.isEmpty) { - return false; - } else { - return true; - } - } - - void updateEmployeePopUp(int index, double width) { - setState(() { - accessController.text = widget.employees[index].access; - typeController.text = widget.employees[index].title; - fnameController.text = widget.employees[index].fname; - lnameController.text = widget.employees[index].lname; - }); + void updateEmployeePopUp(BusinessEmployee employee) { showDialog( context: context, barrierDismissible: false, - builder: (context) => MihPackageWindow( - fullscreen: false, - windowTitle: "Employee Details", - menuOptions: [ - SpeedDialChild( - child: Icon( - Icons.delete, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - label: "Delete Employee", - labelBackgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - labelStyle: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontWeight: FontWeight.bold, - ), - backgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onTap: () { - showDeleteWarning(index); - }, - ), - ], - onWindowTapClose: () { - Navigator.pop(context); - }, - windowBody: Padding( - padding: - MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.05) - : const EdgeInsets.symmetric(horizontal: 0), - child: Column( - children: [ - MihForm( - formKey: _formKey, - formFields: [ - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: fnameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "First Name", - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: lnameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Surname", - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: typeController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Title", - ), - // MihDropdownField( - // controller: typeController, - // hintText: "Title", - // dropdownOptions: const ["Doctor", "Assistant", "Other"], - // editable: true, - // enableSearch: true, - // validator: (value) { - // return MihValidationServices().isEmpty(value); - // }, - // requiredText: true, - // ), - const SizedBox(height: 10.0), - MihDropdownField( - controller: accessController, - hintText: "Access Type", - dropdownOptions: const ["Full", "Partial"], - editable: true, - enableSearch: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - requiredText: true, - ), - const SizedBox(height: 20.0), - Center( - child: MihButton( - onPressed: () { - if (_formKey.currentState!.validate()) { - if (isRequiredFieldsCaptured()) { - updateEmployeeAPICall(index); - } else { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage( - errorType: "Input Error"); - }, - ); - } - } else { - MihAlertServices().formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - width: 300, - child: Text( - "Update", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ], - ), - ), + builder: (context) => MihEditEmployeeDetailsWindow( + employee: employee, ), ); } - void showDeleteWarning(int index) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => MIHDeleteMessage( - deleteType: "Employee", - onTap: () { - deleteNoteApiCall(index); - })); - } - - @override - void dispose() { - accessController.dispose(); - typeController.dispose(); - fnameController.dispose(); - lnameController.dispose(); - super.dispose(); - } - @override Widget build(BuildContext context) { - double screenWidth = MediaQuery.of(context).size.width; - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - separatorBuilder: (BuildContext context, index) { - return Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - }, - itemCount: widget.employees.length, - itemBuilder: (context, index) { - //final patient = widget.patients[index].id_no.contains(widget.searchString); - //print(index); - var isMe = ""; - if (widget.arguments.signedInUser.app_id == - widget.employees[index].app_id) { - isMe = "(You)"; - } - return ListTile( - title: Text( - "${widget.employees[index].fname} ${widget.employees[index].lname} - ${widget.employees[index].title} $isMe"), - subtitle: Text( - "${widget.employees[index].username}\n${widget.employees[index].email}\nAccess: ${widget.employees[index].access}", - style: TextStyle( + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, index) { + return Divider( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - onTap: () { - updateEmployeePopUp(index, screenWidth); + ); + }, + itemCount: mzansiProfileProvider.employeeList!.length, + itemBuilder: (context, index) { + //final patient = widget.patients[index].id_no.contains(widget.searchString); + //print(index); + BusinessEmployee employee = + mzansiProfileProvider.employeeList![index]; + String isMe = ""; + if (mzansiProfileProvider.user!.app_id == + mzansiProfileProvider.employeeList![index].app_id) { + isMe = "(You)"; + } + return ListTile( + title: Text( + "${mzansiProfileProvider.employeeList![index].fname} ${mzansiProfileProvider.employeeList![index].lname} - ${mzansiProfileProvider.employeeList![index].title} $isMe"), + subtitle: Text( + "${mzansiProfileProvider.employeeList![index].username}\n${mzansiProfileProvider.employeeList![index].email}\nAccess: ${mzansiProfileProvider.employeeList![index].access}", + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + onTap: () { + updateEmployeePopUp(employee); + }, + ); }, ); }, diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart index c1c6e870..cb3476fa 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart @@ -1,32 +1,14 @@ -import 'dart:convert'; - -import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -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_packages/mzansi_profile/business_profile/components/mih_add_employee_window.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:flutter/material.dart'; -import 'package:supertokens_flutter/http.dart' as http; +import 'package:provider/provider.dart'; class BuildUserList extends StatefulWidget { - final List users; - final BusinessArguments arguments; - const BuildUserList({ super.key, - required this.users, - required this.arguments, }); @override @@ -34,314 +16,61 @@ class BuildUserList extends StatefulWidget { } class _BuildUserListState extends State { - TextEditingController accessController = TextEditingController(); - TextEditingController typeController = TextEditingController(); - TextEditingController usernameController = TextEditingController(); - TextEditingController emailController = TextEditingController(); - - final _formKey = GlobalKey(); final baseAPI = AppEnviroment.baseApiUrl; - Future createBusinessUserAPICall(int index) async { - showDialog( - context: context, - builder: (context) { - return const Mihloadingcircle(); - }, - ); - var response = await http.post( - Uri.parse("$baseAPI/business-user/insert/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "business_id": widget.arguments.business!.business_id, - "app_id": widget.users[index].app_id, - "signature": "", - "sig_path": "", - "title": "", - "access": accessController.text, - }), - ); - if (response.statusCode == 201) { - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pushNamed( - // '/business-profile/manage', - // arguments: BusinessArguments( - // widget.arguments.signedInUser, - // widget.arguments.businessUser, - // widget.arguments.business, - // ), - // ); - String message = - "${widget.users[index].username} is now apart of your team with ${accessController.text} access to ${widget.arguments.business!.Name}"; - successPopUp(message, false); - } else { - internetConnectionPopUp(); - } - } - - void successPopUp(String message, bool stayOnPersonalSide) { - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.check_circle_outline_rounded, - size: 150, - color: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: "Successfully Updated Profile", - alertBody: Column( - children: [ - Text( - message, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 15, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 25), - Center( - child: MihButton( - onPressed: () { - context.goNamed( - 'mihHome', - extra: stayOnPersonalSide, - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - elevation: 10, - width: 300, - child: Text( - "Dismiss", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ) - ], - ), - alertColour: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - // return MIHSuccessMessage( - // successType: "Success", - // successMessage: message, - // ); - }, - ); - } - - bool isRequiredFieldsCaptured() { - if (accessController.text.isEmpty) { - return false; - } else { - return true; - } - } - - void internetConnectionPopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); - } - String hideEmail(String email) { var firstLetter = email[0]; var end = email.split("@")[1]; return "$firstLetter********@$end"; } - void addEmployeePopUp(int index, double width) { - setState(() { - //accessController.text = widget.users[index].access; - //typeController.text = widget.users[index].title; - // var fnameInitial = widget.users[index].fname[0]; - // var lnameInitial = widget.users[index].lname[0]; - usernameController.text = widget.users[index].username; - emailController.text = hideEmail(widget.users[index].email); - }); + void addEmployeePopUp( + MzansiProfileProvider profileProvider, int index, double width) { showDialog( - context: context, - barrierDismissible: false, - builder: (context) => MihPackageWindow( - fullscreen: false, - windowTitle: "Add Employee", - windowBody: Padding( - padding: - MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.05) - : const EdgeInsets.symmetric(horizontal: 0), - child: Column( - children: [ - MihForm( - formKey: _formKey, - formFields: [ - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: usernameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Username", - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: emailController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Email", - ), - const SizedBox(height: 10.0), - // MihTextFormField( - // fillColor: MihColors.getSecondaryColor( - // MzansiInnovationHub.of(context)!.theme.mode == - // "Dark"), - // inputColor: MihColors.getPrimaryColor( - // MzansiInnovationHub.of(context)!.theme.mode == - // "Dark"), - // controller: typeController, - // multiLineInput: false, - // requiredText: true, - // readOnly: true, - // hintText: "Title", - // ), - // MihDropdownField( - // controller: typeController, - // hintText: "Title", - // dropdownOptions: const ["Doctor", "Assistant", "Other"], - // editable: true, - // enableSearch: true, - // validator: (value) { - // return MihValidationServices().isEmpty(value); - // }, - // requiredText: true, - // ), - // const SizedBox(height: 10.0), - MihDropdownField( - controller: accessController, - hintText: "Access Type", - dropdownOptions: const ["Full", "Partial"], - editable: true, - enableSearch: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - requiredText: true, - ), - const SizedBox(height: 15.0), - Center( - child: MihButton( - onPressed: () { - if (_formKey.currentState!.validate()) { - if (isRequiredFieldsCaptured()) { - createBusinessUserAPICall(index); - } else { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage( - errorType: "Input Error"); - }, - ); - } - } else { - MihAlertServices() - .formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - width: 300, - child: Text( - "Add", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ], - ), - ), - onWindowTapClose: () { - Navigator.pop(context); - })); - } - - @override - void dispose() { - accessController.dispose(); - typeController.dispose(); - usernameController.dispose(); - emailController.dispose(); - super.dispose(); + context: context, + barrierDismissible: false, + builder: (context) => MihAddEmployeeWindow( + user: profileProvider.userSearchResults[index], + ), + ); } @override Widget build(BuildContext context) { double screenWidth = MediaQuery.of(context).size.width; - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - separatorBuilder: (BuildContext context, index) { - return Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - }, - itemCount: widget.users.length, - itemBuilder: (context, index) { - var isYou = ""; - if (widget.arguments.signedInUser.app_id == - widget.users[index].app_id) { - isYou = "(You)"; - } - return ListTile( - title: Text("@${widget.users[index].username} $isYou"), - subtitle: Text( - "Email: ${hideEmail(widget.users[index].email)}", - style: TextStyle( + return Consumer( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, index) { + return Divider( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - onTap: () { - addEmployeePopUp(index, screenWidth); + ); + }, + itemCount: profileProvider.userSearchResults.length, + itemBuilder: (context, index) { + var isYou = ""; + if (profileProvider.user!.app_id == + profileProvider.userSearchResults[index].app_id) { + isYou = "(You)"; + } + return ListTile( + title: Text( + "@${profileProvider.userSearchResults[index].username} $isYou"), + subtitle: Text( + "Email: ${hideEmail(profileProvider.userSearchResults[index].email)}", + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + onTap: () { + addEmployeePopUp(profileProvider, index, screenWidth); + }, + ); }, ); }, diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_add_bookmark_alert.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_add_bookmark_alert.dart index 6e70de6b..e50a5d59 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_add_bookmark_alert.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_add_bookmark_alert.dart @@ -1,21 +1,23 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart'; -import 'package:supertokens_flutter/supertokens.dart'; +import 'package:provider/provider.dart'; class MihAddBookmarkAlert extends StatefulWidget { final Business business; + final void Function()? onSuccessDismissPressed; const MihAddBookmarkAlert({ super.key, required this.business, + required this.onSuccessDismissPressed, }); @override @@ -23,16 +25,16 @@ class MihAddBookmarkAlert extends StatefulWidget { } class _MihAddBookmarkAlertState extends State { - Future addBookmark(String business_id) async { + Future addBookmark( + MzansiProfileProvider profileProvider, String business_id) async { showDialog( context: context, builder: (context) { return const Mihloadingcircle(); }, ); - String user_id = await SuperTokens.getUserId(); await MihMzansiDirectoryServices() - .addBookmarkedBusiness(user_id, business_id) + .addBookmarkedBusiness(profileProvider.user!.app_id, business_id) .then((statusCode) { context.pop(); if (statusCode == 201) { @@ -77,14 +79,9 @@ class _MihAddBookmarkAlertState extends State { Center( child: MihButton( onPressed: () { - context.goNamed( - "mzansiDirectory", - extra: MzansiDirectoryArguments( - personalSearch: false, - startSearchText: widget.business.Name, - packageIndex: 1, - ), - ); + widget.onSuccessDismissPressed!.call(); + context.pop(); + context.pop(); }, buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -117,69 +114,76 @@ class _MihAddBookmarkAlertState extends State { @override Widget build(BuildContext context) { - return MihPackageAlert( - alertColour: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - alertIcon: Icon( - Icons.warning_rounded, - size: 100, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: "Bookmark Business", - alertBody: Column( - children: [ - Text( - "Are you sure you want to save ${widget.business.Name} to your Mzansi Directory?", - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 15, - ), + return Consumer( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + Widget? child) { + return MihPackageAlert( + alertColour: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + alertIcon: Icon( + Icons.warning_rounded, + size: 100, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), - const SizedBox(height: 25), - Wrap( - spacing: 10, - runSpacing: 10, + alertTitle: "Bookmark Business", + alertBody: Column( children: [ - MihButton( - width: 300, - onPressed: () async { - Navigator.of(context).pop(); - }, - buttonColor: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - child: Text( - "Cancel", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), + Text( + "Are you sure you want to save ${widget.business.Name} to your Mzansi Directory?", + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, ), ), - MihButton( - width: 300, - onPressed: () { - addBookmark(widget.business.business_id); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - child: Text( - "Bookmark Business", - style: TextStyle( - color: MihColors.getPrimaryColor( + const SizedBox(height: 25), + Wrap( + spacing: 10, + runSpacing: 10, + children: [ + MihButton( + width: 300, + onPressed: () async { + Navigator.of(context).pop(); + }, + buttonColor: MihColors.getRedColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, + child: Text( + "Cancel", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), ), - ), + MihButton( + width: 300, + onPressed: () { + addBookmark(profileProvider, widget.business.business_id); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + child: Text( + "Bookmark Business", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ], ), ], ), - ], - ), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_add_employee_window.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_add_employee_window.dart new file mode 100644 index 00000000..daf43813 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_add_employee_window.dart @@ -0,0 +1,250 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_employee_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; + +class MihAddEmployeeWindow extends StatefulWidget { + final AppUser user; + const MihAddEmployeeWindow({ + super.key, + required this.user, + }); + + @override + State createState() => _MihAddEmployeeWindowState(); +} + +class _MihAddEmployeeWindowState extends State { + TextEditingController accessController = TextEditingController(); + TextEditingController usernameController = TextEditingController(); + TextEditingController emailController = TextEditingController(); + final _formKey = GlobalKey(); + + Future createBusinessUserAPICall( + MzansiProfileProvider mzansiProfileProvider) async { + int statusCode = await MihBusinessEmployeeServices().addEmployee( + mzansiProfileProvider, + widget.user, + accessController.text, + context, + ); + if (statusCode == 201) { + String message = + "${widget.user.username} is now apart of your team with ${accessController.text} access to ${mzansiProfileProvider.business!.Name}"; + successPopUp(message, false); + } else { + internetConnectionPopUp(); + } + } + + void successPopUp(String message, bool stayOnPersonalSide) { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.check_circle_outline_rounded, + size: 150, + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: "Successfully Updated Profile", + alertBody: Column( + children: [ + Text( + message, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + context.pop(); + context.pop(); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Dismiss", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + // return MIHSuccessMessage( + // successType: "Success", + // successMessage: message, + // ); + }, + ); + } + + void internetConnectionPopUp() { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Internet Connection"); + }, + ); + } + + bool isRequiredFieldsCaptured() { + if (accessController.text.isEmpty) { + return false; + } else { + return true; + } + } + + @override + void dispose() { + super.dispose(); + accessController.dispose(); + usernameController.dispose(); + emailController.dispose(); + } + + @override + void initState() { + super.initState(); + usernameController.text = widget.user.username; + emailController.text = widget.user.email; + } + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return MihPackageWindow( + fullscreen: false, + windowTitle: "Add Employee", + windowBody: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: screenWidth * 0.05) + : const EdgeInsets.symmetric(horizontal: 0), + child: Column( + children: [ + MihForm( + formKey: _formKey, + formFields: [ + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: usernameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Username", + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: emailController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Email", + ), + const SizedBox(height: 10.0), + MihDropdownField( + controller: accessController, + hintText: "Access Type", + dropdownOptions: const ["Full", "Partial"], + editable: true, + enableSearch: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + requiredText: true, + ), + const SizedBox(height: 15.0), + Center( + child: MihButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + if (isRequiredFieldsCaptured()) { + createBusinessUserAPICall(mzansiProfileProvider); + } else { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage( + errorType: "Input Error"); + }, + ); + } + } else { + MihAlertServices().formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Add", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ], + ), + ), + onWindowTapClose: () { + Navigator.pop(context); + }, + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart index 124bb903..7f5a1b39 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart @@ -7,23 +7,24 @@ import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_review import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_add_bookmark_alert.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_delete_bookmark_alert.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_review_business_window.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart'; +import 'package:provider/provider.dart'; import 'package:redacted/redacted.dart'; import 'package:supertokens_flutter/supertokens.dart'; import 'package:url_launcher/url_launcher.dart'; class MihBusinessCard extends StatefulWidget { final Business business; - final String? startUpSearch; final double width; const MihBusinessCard({ super.key, required this.business, - required this.startUpSearch, required this.width, }); @@ -409,274 +410,292 @@ class _MihBusinessCardState extends State { @override Widget build(BuildContext context) { // double screenWidth = MediaQuery.of(context).size.width; - return Material( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark") - .withValues(alpha: 0.6), - borderRadius: BorderRadius.circular(25), - elevation: 10, - shadowColor: Colors.black, - child: Container( - decoration: BoxDecoration( + return Consumer( + builder: (BuildContext context, MzansiDirectoryProvider directoryProvider, + Widget? child) { + return Material( color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - borderRadius: BorderRadius.circular(10), - ), - child: Column( - children: [ - const SizedBox(height: 10), - _buildContactInfo( - "Call", - "Give us a quick call.", - Icons.phone, - MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark") + .withValues(alpha: 0.6), + borderRadius: BorderRadius.circular(25), + elevation: 10, + shadowColor: Colors.black, + child: Container( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - false, - () { - // print("Calling ${widget.cellNumber}"); - _makePhoneCall(widget.business.contact_no); - }, + borderRadius: BorderRadius.circular(10), ), - Divider( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - _buildContactInfo( - "Email", - "Send us an email.", - Icons.email, - MihColors.getPinkColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - false, - () { - // print("Emailing ${widget.email}"); - _launchEmail( - widget.business.bus_email, - "Inquiery about ${widget.business.Name}", - "Dear ${widget.business.Name},\n\nI would like to inquire about your services.\n\nBest regards,\n", - ); - }, - ), - Visibility( - visible: isValidGps(widget.business.gps_location), - child: Column( - children: [ - Divider( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + child: Column( + children: [ + const SizedBox(height: 10), + _buildContactInfo( + "Call", + "Give us a quick call.", + Icons.phone, + MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + false, + () { + // print("Calling ${widget.cellNumber}"); + _makePhoneCall(widget.business.contact_no); + }, + ), + Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + _buildContactInfo( + "Email", + "Send us an email.", + Icons.email, + MihColors.getPinkColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + false, + () { + // print("Emailing ${widget.email}"); + _launchEmail( + widget.business.bus_email, + "Inquiery about ${widget.business.Name}", + "Dear ${widget.business.Name},\n\nI would like to inquire about your services.\n\nBest regards,\n", + ); + }, + ), + Visibility( + visible: isValidGps(widget.business.gps_location), + child: Column( + children: [ + Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + _buildContactInfo( + "Location", + "Come visit us.", + Icons.location_on, + MihColors.getOrangeColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + false, + () { + final latitude = double.parse( + widget.business.gps_location.split(',')[0]); + final longitude = double.parse( + widget.business.gps_location.split(',')[1]); + _launchGoogleMapsWithUrl( + latitude: latitude, + longitude: longitude, + ); + }, + ), + ], ), - _buildContactInfo( - "Location", - "Come visit us.", - Icons.location_on, - MihColors.getOrangeColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - false, - () { - final latitude = double.parse( - widget.business.gps_location.split(',')[0]); - final longitude = double.parse( - widget.business.gps_location.split(',')[1]); - _launchGoogleMapsWithUrl( - latitude: latitude, - longitude: longitude, + ), + Visibility( + visible: widget.business.website.isNotEmpty && + widget.business.website != "", + child: Column( + children: [ + Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + _buildContactInfo( + "Website", + "Find out more about us.", + Icons.vpn_lock, + MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + false, + () { + _launchWebsite(widget.business.website); + }, + ), + ], + ), + ), + FutureBuilder( + future: _businessReviewFuture, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == + ConnectionState.waiting) { + // return const SizedBox.shrink(); + return Column( + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 10.0), + child: Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + Container( + child: _buildContactInfo( + "Loading Rating", + "Loading your rating.", + Icons.star_rate_rounded, + MihColors.getYellowColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + true, + null, + ), + ).redacted(context: context, redact: true), + ], ); - }, - ), - ], - ), + } else { + BusinessReview? businessReview = asyncSnapshot.data; + String ratingDisplayTitle = ""; + if (businessReview == null) { + ratingDisplayTitle = "Rate Us"; + } else { + ratingDisplayTitle = "Update Rating"; + } + return Column( + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 10.0), + child: Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + _buildContactInfo( + ratingDisplayTitle, + "Let us know how we are doing.", + Icons.star_rate_rounded, + MihColors.getYellowColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + false, + () { + businessReviewRatingWindow(directoryProvider, + businessReview, true, widget.width); + }, + ), + ], + ); + } + }, + ), + FutureBuilder( + future: _bookmarkedBusinessFuture, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == + ConnectionState.waiting) { + // return const SizedBox.shrink(); + return Column( + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 10.0), + child: Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + Container( + child: _buildContactInfo( + "Loading Bookmark", + "Loading your bookmark.", + Icons.bookmark_add_rounded, + MihColors.getBluishPurpleColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + true, + null, + ), + ), + ], + ); + } else { + BookmarkedBusiness? bookmarkBusiness = asyncSnapshot.data; + String bookmarkDisplayTitle = ""; + if (bookmarkBusiness == null) { + bookmarkDisplayTitle = "Bookmark Us"; + } else { + bookmarkDisplayTitle = "Remove Bookmark"; + } + return Column( + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 10.0), + child: Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + _buildContactInfo( + bookmarkDisplayTitle, + "Save us for later.", + bookmarkBusiness == null + ? Icons.bookmark_add_rounded + : Icons.bookmark_remove_rounded, + MihColors.getBluishPurpleColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + false, + () { + // _launchWebsite(widget.website); + if (bookmarkBusiness == null) { + showAddBookmarkAlert(); + } else { + showDeleteBookmarkAlert(bookmarkBusiness); + } + }, + ), + ], + ); + } + }, + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 10.0), + // child: Divider( + // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + // ), + // _buildContactInfo( + // "Bookmark", + // "Save us for later.", + // Icons.bookmark_add_rounded, + // MihColors.getBluishPurpleColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // () { + // // _launchWebsite(widget.website); + // print("Saving ${widget.business.Name} to Directory"); + // showBookmarkAlert(); + // }, + // ), + const SizedBox(height: 10), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 10.0), + // child: Divider( + // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + // ), + ], ), - Visibility( - visible: widget.business.website.isNotEmpty && - widget.business.website != "", - child: Column( - children: [ - Divider( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - _buildContactInfo( - "Website", - "Find out more about us.", - Icons.vpn_lock, - MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - false, - () { - _launchWebsite(widget.business.website); - }, - ), - ], - ), - ), - FutureBuilder( - future: _businessReviewFuture, - builder: (context, asyncSnapshot) { - if (asyncSnapshot.connectionState == ConnectionState.waiting) { - // return const SizedBox.shrink(); - return Column( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Divider( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - Container( - child: _buildContactInfo( - "Loading Rating", - "Loading your rating.", - Icons.star_rate_rounded, - MihColors.getYellowColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - true, - null, - ), - ).redacted(context: context, redact: true), - ], - ); - } else { - BusinessReview? businessReview = asyncSnapshot.data; - String ratingDisplayTitle = ""; - if (businessReview == null) { - ratingDisplayTitle = "Rate Us"; - } else { - ratingDisplayTitle = "Update Rating"; - } - return Column( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Divider( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - _buildContactInfo( - ratingDisplayTitle, - "Let us know how we are doing.", - Icons.star_rate_rounded, - MihColors.getYellowColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - false, - () { - businessReviewRatingWindow( - businessReview, true, widget.width); - }, - ), - ], - ); - } - }, - ), - FutureBuilder( - future: _bookmarkedBusinessFuture, - builder: (context, asyncSnapshot) { - if (asyncSnapshot.connectionState == ConnectionState.waiting) { - // return const SizedBox.shrink(); - return Column( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Divider( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - Container( - child: _buildContactInfo( - "Loading Bookmark", - "Loading your bookmark.", - Icons.bookmark_add_rounded, - MihColors.getBluishPurpleColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - true, - null, - ), - ), - ], - ); - } else { - BookmarkedBusiness? bookmarkBusiness = asyncSnapshot.data; - String bookmarkDisplayTitle = ""; - if (bookmarkBusiness == null) { - bookmarkDisplayTitle = "Bookmark Us"; - } else { - bookmarkDisplayTitle = "Remove Bookmark"; - } - return Column( - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Divider( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - _buildContactInfo( - bookmarkDisplayTitle, - "Save us for later.", - bookmarkBusiness == null - ? Icons.bookmark_add_rounded - : Icons.bookmark_remove_rounded, - MihColors.getBluishPurpleColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - false, - () { - // _launchWebsite(widget.website); - if (bookmarkBusiness == null) { - showAddBookmarkAlert(); - } else { - showDeleteBookmarkAlert(bookmarkBusiness); - } - }, - ), - ], - ); - } - }, - ), - // Padding( - // padding: const EdgeInsets.symmetric(horizontal: 10.0), - // child: Divider( - // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // ), - // _buildContactInfo( - // "Bookmark", - // "Save us for later.", - // Icons.bookmark_add_rounded, - // MihColors.getBluishPurpleColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // () { - // // _launchWebsite(widget.website); - // print("Saving ${widget.business.Name} to Directory"); - // showBookmarkAlert(); - // }, - // ), - const SizedBox(height: 10), - // Padding( - // padding: const EdgeInsets.symmetric(horizontal: 10.0), - // child: Divider( - // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // ), - ], - ), - ), + ), + ); + }, ); } Future businessReviewRatingWindow( - BusinessReview? myReview, bool previouslyRated, double width) async { + MzansiDirectoryProvider directoryProvider, + BusinessReview? myReview, + bool previouslyRated, + double width) async { if (_isUserSignedIn) { showDialog( context: context, @@ -685,6 +704,17 @@ class _MihBusinessCardState extends State { businessReview: myReview, screenWidth: width, readOnly: false, + onSuccessDismissPressed: () async { + List? businessSearchResults = []; + businessSearchResults = await MihBusinessDetailsServices() + .searchBusinesses(directoryProvider.searchTerm, + directoryProvider.businessTypeFilter, context); + directoryProvider.setSearchedBusinesses( + searchedBusinesses: businessSearchResults); + setState(() { + _businessReviewFuture = getUserReview(); + }); + }, ), ); } else { @@ -698,6 +728,11 @@ class _MihBusinessCardState extends State { context: context, builder: (context) => MihAddBookmarkAlert( business: widget.business, + onSuccessDismissPressed: () { + setState(() { + _bookmarkedBusinessFuture = getUserBookmark(); + }); + }, ), ); } else { @@ -712,7 +747,12 @@ class _MihBusinessCardState extends State { builder: (context) => MihDeleteBookmarkAlert( business: widget.business, bookmarkBusiness: bookmarkBusiness, - startUpSearch: widget.startUpSearch, + onSuccessDismissPressed: () { + setState(() { + _bookmarkedBusinessFuture = getUserBookmark(); + }); + }, + // startUpSearch: widget.startUpSearch, )); } else { showSignInRequiredAlert(); diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_delete_bookmark_alert.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_delete_bookmark_alert.dart index 4d5dbae8..c5496820 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_delete_bookmark_alert.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_delete_bookmark_alert.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; @@ -14,12 +13,14 @@ import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services class MihDeleteBookmarkAlert extends StatefulWidget { final Business business; final BookmarkedBusiness? bookmarkBusiness; - final String? startUpSearch; + final void Function()? onSuccessDismissPressed; + // final String? startUpSearch; const MihDeleteBookmarkAlert({ super.key, required this.business, required this.bookmarkBusiness, - required this.startUpSearch, + required this.onSuccessDismissPressed, + // required this.startUpSearch, }); @override @@ -80,14 +81,17 @@ class _MihDeleteBookmarkAlertState extends State { Center( child: MihButton( onPressed: () { - context.goNamed( - "mzansiDirectory", - extra: MzansiDirectoryArguments( - personalSearch: false, - startSearchText: widget.business.Name, - packageIndex: 1, - ), - ); + // context.goNamed( + // "mzansiDirectory", + // extra: MzansiDirectoryArguments( + // personalSearch: false, + // startSearchText: widget.business.Name, + // packageIndex: 1, + // ), + // ); + widget.onSuccessDismissPressed!.call(); + context.pop(); + context.pop(); }, buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_edit_employee_details_window.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_edit_employee_details_window.dart new file mode 100644 index 00000000..0b2bd362 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_edit_employee_details_window.dart @@ -0,0 +1,319 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_speed_dial/flutter_speed_dial.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_employee_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; + +class MihEditEmployeeDetailsWindow extends StatefulWidget { + final BusinessEmployee employee; + const MihEditEmployeeDetailsWindow({ + super.key, + required this.employee, + }); + + @override + State createState() => + _MihEditEmployeeDetailsWindowState(); +} + +class _MihEditEmployeeDetailsWindowState + extends State { + TextEditingController accessController = TextEditingController(); + TextEditingController titleController = TextEditingController(); + TextEditingController fnameController = TextEditingController(); + TextEditingController lnameController = TextEditingController(); + final _formKey = GlobalKey(); + + void updateEmployeeAPICall( + MzansiProfileProvider mzansiProfileProvider) async { + int statusCode = await MihBusinessEmployeeServices().updateEmployeeDetails( + mzansiProfileProvider, + widget.employee, + titleController.text, + accessController.text, + context); + if (statusCode == 200) { + String message = "Your employees details have been updated."; + successPopUp(message, false); + } else { + internetConnectionPopUp(); + } + } + + Future deleteNoteApiCall() async { + int statusCode = await MihBusinessEmployeeServices().deleteEmployee( + context.read(), + widget.employee, + context, + ); + if (statusCode == 200) { + String message = + "The employee has been deleted successfully. This means they will no longer have access to your business profile"; + successPopUp(message, false); + } else { + internetConnectionPopUp(); + } + } + + void showDeleteWarning() { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => MIHDeleteMessage( + deleteType: "Employee", + onTap: () { + deleteNoteApiCall(); + })); + } + + void successPopUp(String message, bool stayOnPersonalSide) { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.check_circle_outline_rounded, + size: 150, + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: "Successfully Updated Profile", + alertBody: Column( + children: [ + Text( + message, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + context.pop(); + context.pop(); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Dismiss", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + // return MIHSuccessMessage( + // successType: "Success", + // successMessage: message, + // ); + }, + ); + } + + void internetConnectionPopUp() { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Internet Connection"); + }, + ); + } + + bool isRequiredFieldsCaptured() { + if (accessController.text.isEmpty || titleController.text.isEmpty) { + return false; + } else { + return true; + } + } + + @override + void dispose() { + accessController.dispose(); + titleController.dispose(); + fnameController.dispose(); + lnameController.dispose(); + super.dispose(); + } + + @override + void initState() { + super.initState(); + fnameController.text = widget.employee.fname; + lnameController.text = widget.employee.lname; + titleController.text = widget.employee.title; + accessController.text = widget.employee.access; + } + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return MihPackageWindow( + fullscreen: false, + windowTitle: "Employee Details", + menuOptions: [ + SpeedDialChild( + child: Icon( + Icons.delete, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + label: "Delete Employee", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onTap: () { + showDeleteWarning(); + }, + ), + ], + onWindowTapClose: () { + Navigator.pop(context); + }, + windowBody: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: screenWidth * 0.05) + : const EdgeInsets.symmetric(horizontal: 0), + child: Column( + children: [ + MihForm( + formKey: _formKey, + formFields: [ + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: fnameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "First Name", + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: lnameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Surname", + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: titleController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Title", + ), + const SizedBox(height: 10.0), + MihDropdownField( + controller: accessController, + hintText: "Access Type", + dropdownOptions: const ["Full", "Partial"], + editable: true, + enableSearch: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + requiredText: true, + ), + const SizedBox(height: 20.0), + Center( + child: MihButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + if (isRequiredFieldsCaptured()) { + updateEmployeeAPICall(mzansiProfileProvider); + } else { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage( + errorType: "Input Error"); + }, + ); + } + } else { + MihAlertServices().formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Update", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_review_business_window.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_review_business_window.dart index 48de194b..c26477a5 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_review_business_window.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_review_business_window.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_review.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; @@ -13,23 +12,28 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; -import 'package:supertokens_flutter/supertokens.dart'; +import 'package:provider/provider.dart'; class MihReviewBusinessWindow extends StatefulWidget { final Business business; final BusinessReview? businessReview; final double screenWidth; final bool readOnly; + final void Function()? onSuccessDismissPressed; const MihReviewBusinessWindow({ super.key, required this.business, required this.businessReview, required this.screenWidth, required this.readOnly, + required this.onSuccessDismissPressed, }); @override @@ -47,9 +51,8 @@ class _MihReviewBusinessWindowState extends State { TextEditingController(); late final VoidCallback _reviewDescriptionListener; final ValueNotifier _counter = ValueNotifier(0); - String userId = ""; - void showDeleteReviewAlert() { + void showDeleteReviewAlert(MzansiDirectoryProvider directoryProvider) { showDialog( context: context, builder: (context) => MihPackageAlert( @@ -93,10 +96,11 @@ class _MihReviewBusinessWindowState extends State { widget.businessReview!.rating_score, widget.business.rating, ) - .then((statusCode) { + .then((statusCode) async { context.pop(); //Remove loading dialog context.pop(); //Remove delete dialog if (statusCode == 200) { + await refreshBusiness(directoryProvider); context.pop(); //Remove window successPopUp( "Successfully Deleted Review!", @@ -160,7 +164,19 @@ class _MihReviewBusinessWindowState extends State { } } - void submitForm() async { + Future refreshBusiness( + MzansiDirectoryProvider directoryProvider) async { + Business? refresedBusiness = await MihBusinessDetailsServices() + .getBusinessDetailsByBusinessId(widget.business.business_id); + if (refresedBusiness != null) { + directoryProvider.setSelectedBusiness(business: refresedBusiness); + } + } + + void submitForm( + MzansiProfileProvider profileProvider, + MzansiDirectoryProvider directoryProvider, + ) async { showDialog( context: context, builder: (context) { @@ -178,9 +194,10 @@ class _MihReviewBusinessWindowState extends State { widget.businessReview!.rating_score, widget.business.rating, ) - .then((statusCode) { + .then((statusCode) async { context.pop(); //Remove loading dialog if (statusCode == 200) { + await refreshBusiness(directoryProvider); context.pop(); successPopUp( "Successfully Updated Review!", @@ -197,16 +214,17 @@ class _MihReviewBusinessWindowState extends State { } else { await MihMzansiDirectoryServices() .addBusinessReview( - userId, + profileProvider.user!.app_id, widget.business.business_id, _reviewTitleController.text, _reviewDescriptionController.text, _reviewScoreController.text, widget.business.rating.isEmpty ? "0.0" : widget.business.rating, ) - .then((statusCode) { + .then((statusCode) async { context.pop(); //Remove loading dialog if (statusCode == 201) { + await refreshBusiness(directoryProvider); context.pop(); successPopUp( "Successfully Added Review!", @@ -250,13 +268,15 @@ class _MihReviewBusinessWindowState extends State { Center( child: MihButton( onPressed: () { - context.goNamed( - "mzansiDirectory", - extra: MzansiDirectoryArguments( - personalSearch: false, - startSearchText: widget.business.Name, - ), - ); + // context.goNamed( + // "mzansiDirectory", + // extra: MzansiDirectoryArguments( + // personalSearch: false, + // startSearchText: widget.business.Name, + // ), + // ); + widget.onSuccessDismissPressed!.call(); + context.pop(); }, buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -323,265 +343,277 @@ class _MihReviewBusinessWindowState extends State { } else { _reviewScoreController.text = "1.0"; // Default score } - SuperTokens.getUserId().then((value) { - setState(() { - userId = value; - }); - }); } @override Widget build(BuildContext context) { // return const Placeholder(); - return MihPackageWindow( - fullscreen: false, - windowTitle: getWindowTitle(), - onWindowTapClose: () { - Navigator.of(context).pop(); - }, - menuOptions: widget.businessReview != null && !widget.readOnly - ? [ - SpeedDialChild( - child: Icon( - Icons.delete, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - label: "Delete Review", - labelBackgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - labelStyle: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontWeight: FontWeight.bold, - ), - backgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onTap: () { - showDeleteReviewAlert(); - }, - ), - ] - : null, - windowBody: MihSingleChildScroll( - child: Padding( - padding: - MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + MzansiDirectoryProvider directoryProvider, Widget? child) { + return MihPackageWindow( + fullscreen: false, + windowTitle: getWindowTitle(), + onWindowTapClose: () { + Navigator.of(context).pop(); + }, + menuOptions: widget.businessReview != null && !widget.readOnly + ? [ + SpeedDialChild( + child: Icon( + Icons.delete, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + label: "Delete Review", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onTap: () { + showDeleteReviewAlert(directoryProvider); + }, + ), + ] + : null, + windowBody: MihSingleChildScroll( + child: Padding( + padding: MzansiInnovationHub.of(context)!.theme.screenType == + "desktop" ? EdgeInsets.symmetric(horizontal: widget.screenWidth * 0.05) : EdgeInsets.symmetric(horizontal: widget.screenWidth * 0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - children: [ - MihForm( - formKey: _formKey, - formFields: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Business Rating", - textAlign: TextAlign.left, - style: TextStyle( - color: MihColors.getSecondaryColor( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + MihForm( + formKey: _formKey, + formFields: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Business Rating", + textAlign: TextAlign.left, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + const SizedBox(height: 4), + widget.readOnly + ? RatingBar.readOnly( + size: 50, + alignment: Alignment.centerLeft, + filledIcon: Icons.star, + emptyIcon: Icons.star_border, + halfFilledIcon: Icons.star_half, + filledColor: MihColors.getYellowColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + // filledColor: MzansiInnovationHub.of(context)! + // .theme + // .secondaryColor(), + emptyColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + halfFilledColor: MihColors.getYellowColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + // MzansiInnovationHub.of(context)! + // .theme + // .secondaryColor(), + isHalfAllowed: true, + initialRating: widget.businessReview != null + ? double.parse(_reviewScoreController.text) + : 1, + maxRating: 5, + ) + : RatingBar( + size: 50, + alignment: Alignment.centerLeft, + filledIcon: Icons.star, + emptyIcon: Icons.star_border, + halfFilledIcon: Icons.star_half, + filledColor: MihColors.getYellowColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + emptyColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + halfFilledColor: MihColors.getYellowColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + isHalfAllowed: true, + initialRating: widget.businessReview != null + ? double.parse(_reviewScoreController.text) + : 1, + maxRating: 5, + onRatingChanged: (double) { + setState(() { + _reviewScoreController.text = + double.toStringAsFixed(1); + }); + print(_reviewScoreController.text); + }, + ), + Visibility( + visible: widget.readOnly, + child: const SizedBox(height: 10), + ), + Visibility( + visible: widget.readOnly, + child: MihTextFormField( + // width: 200, + fillColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 18, - fontWeight: FontWeight.bold, + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: _reviewReviewerController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Reviewer", + validator: (value) { + return null; + }, + ), + ), + const SizedBox(height: 10), + MihTextFormField( + // width: 200, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: _reviewTitleController, + multiLineInput: false, + requiredText: true, + readOnly: widget.readOnly, + hintText: "Review Title", + validator: (value) { + return MihValidationServices() + .isEmpty(_reviewTitleController.text); + }, + ), + const SizedBox(height: 10), + MihTextFormField( + height: 250, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: _reviewDescriptionController, + multiLineInput: true, + requiredText: widget.readOnly, + readOnly: widget.readOnly, + hintText: "Review Description", + validator: (value) { + if (_reviewDescriptionController.text.isEmpty) { + return null; + } else { + return MihValidationServices().validateLength( + _reviewDescriptionController.text, 256); + } + }, + ), + Visibility( + visible: !widget.readOnly, + child: SizedBox( + height: 15, + child: ValueListenableBuilder( + valueListenable: _counter, + builder: (BuildContext context, int value, + Widget? child) { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "$value", + style: TextStyle( + color: getMissionVisionLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 5), + Text( + "/256", + style: TextStyle( + color: getMissionVisionLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + ], + ); + }, + ), + ), + ), + const SizedBox(height: 25), + Visibility( + visible: !widget.readOnly, + child: Center( + child: MihButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + submitForm( + profileProvider, + directoryProvider, + ); + } else { + MihAlertServices() + .formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + widget.businessReview != null + ? "Update Review" + : "Add Review", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), ), ), ], ), - const SizedBox(height: 4), - widget.readOnly - ? RatingBar.readOnly( - size: 50, - alignment: Alignment.centerLeft, - filledIcon: Icons.star, - emptyIcon: Icons.star_border, - halfFilledIcon: Icons.star_half, - filledColor: MihColors.getYellowColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - // filledColor: MzansiInnovationHub.of(context)! - // .theme - // .secondaryColor(), - emptyColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - halfFilledColor: MihColors.getYellowColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - // MzansiInnovationHub.of(context)! - // .theme - // .secondaryColor(), - isHalfAllowed: true, - initialRating: widget.businessReview != null - ? double.parse(_reviewScoreController.text) - : 1, - maxRating: 5, - ) - : RatingBar( - size: 50, - alignment: Alignment.centerLeft, - filledIcon: Icons.star, - emptyIcon: Icons.star_border, - halfFilledIcon: Icons.star_half, - filledColor: MihColors.getYellowColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - emptyColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - halfFilledColor: MihColors.getYellowColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - isHalfAllowed: true, - initialRating: widget.businessReview != null - ? double.parse(_reviewScoreController.text) - : 1, - maxRating: 5, - onRatingChanged: (double) { - setState(() { - _reviewScoreController.text = - double.toStringAsFixed(1); - }); - print(_reviewScoreController.text); - }, - ), - Visibility( - visible: widget.readOnly, - child: const SizedBox(height: 10), - ), - Visibility( - visible: widget.readOnly, - child: MihTextFormField( - // width: 200, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: _reviewReviewerController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Reviewer", - validator: (value) { - return null; - }, - ), - ), - const SizedBox(height: 10), - MihTextFormField( - // width: 200, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: _reviewTitleController, - multiLineInput: false, - requiredText: true, - readOnly: widget.readOnly, - hintText: "Review Title", - validator: (value) { - return MihValidationServices() - .isEmpty(_reviewTitleController.text); - }, - ), - const SizedBox(height: 10), - MihTextFormField( - height: 250, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: _reviewDescriptionController, - multiLineInput: true, - requiredText: widget.readOnly, - readOnly: widget.readOnly, - hintText: "Review Description", - validator: (value) { - if (_reviewDescriptionController.text.isEmpty) { - return null; - } else { - return MihValidationServices().validateLength( - _reviewDescriptionController.text, 256); - } - }, - ), - Visibility( - visible: !widget.readOnly, - child: SizedBox( - height: 15, - child: ValueListenableBuilder( - valueListenable: _counter, - builder: - (BuildContext context, int value, Widget? child) { - return Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - "$value", - style: TextStyle( - color: getMissionVisionLimitColor(256), - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(width: 5), - Text( - "/256", - style: TextStyle( - color: getMissionVisionLimitColor(256), - fontWeight: FontWeight.bold, - ), - ), - ], - ); - }, - ), - ), - ), - const SizedBox(height: 25), - Visibility( - visible: !widget.readOnly, - child: Center( - child: MihButton( - onPressed: () { - if (_formKey.currentState!.validate()) { - submitForm(); - } else { - MihAlertServices().formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - width: 300, - child: Text( - widget.businessReview != null - ? "Update Review" - : "Add Review", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ), ], ), - ], + ), ), - ), - ), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_update_business_details_window.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_update_business_details_window.dart new file mode 100644 index 00000000..a5cef9de --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_update_business_details_window.dart @@ -0,0 +1,705 @@ +import 'package:country_code_picker/country_code_picker.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +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_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; + +class MihUpdateBusinessDetailsWindow extends StatefulWidget { + final double width; + const MihUpdateBusinessDetailsWindow({ + super.key, + required this.width, + }); + + @override + State createState() => + _MihUpdateBusinessDetailsWindowState(); +} + +class _MihUpdateBusinessDetailsWindowState + extends State { + final _formKey = GlobalKey(); + PlatformFile? newSelectedLogoPic; + final fileNameController = TextEditingController(); + final regController = TextEditingController(); + final nameController = TextEditingController(); + final typeController = TextEditingController(); + final practiceNoController = TextEditingController(); + final vatNoController = TextEditingController(); + final countryCodeController = TextEditingController(); + final contactController = TextEditingController(); + final emailController = TextEditingController(); + final locationController = TextEditingController(); + final websiteController = TextEditingController(); + final ratingController = TextEditingController(); + final missionVisionController = TextEditingController(); + final ValueNotifier _counter = ValueNotifier(0); + late String env; + + void setContactNumberControllers( + MzansiProfileProvider mzansiProfileProvider) { + if (mzansiProfileProvider.business!.contact_no[0] == "+") { + List contactDetails = + mzansiProfileProvider.business!.contact_no.split("-"); + setState(() { + countryCodeController.text = contactDetails[0]; + contactController.text = contactDetails[1]; + }); + } else { + setState(() { + countryCodeController.text = "+27"; + contactController.text = mzansiProfileProvider.business!.contact_no; + }); + } + } + + void setControllers() { + MzansiProfileProvider mzansiProfileProvider = + context.read(); + setState(() { + fileNameController.text = + mzansiProfileProvider.business!.logo_path.split("/").last; + regController.text = mzansiProfileProvider.business!.registration_no; + nameController.text = mzansiProfileProvider.business!.Name; + typeController.text = mzansiProfileProvider.business!.type; + practiceNoController.text = mzansiProfileProvider.business!.practice_no; + vatNoController.text = mzansiProfileProvider.business!.vat_no; + emailController.text = mzansiProfileProvider.business!.bus_email; + locationController.text = mzansiProfileProvider.business!.gps_location; + websiteController.text = mzansiProfileProvider.business!.website; + ratingController.text = mzansiProfileProvider.business!.rating; + missionVisionController.text = + mzansiProfileProvider.business!.mission_vision; + }); + setContactNumberControllers(mzansiProfileProvider); + if (AppEnviroment.getEnv() == "Prod") { + env = "Prod"; + } else { + env = "Dev"; + } + } + + Color getMissionVisionLimitColor(int limit) { + if (_counter.value <= limit) { + return MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } else { + return MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } + } + + void _updateMissionVisionCounter() { + // New function name + // No need for setState since you are using a ValueNotifier for _counter + _counter.value = missionVisionController.text.characters.length; + } + + String getNumberWithCountryCode() { + String numberWithoutBeginingZero = ""; + if (contactController.text[0] == "0") { + numberWithoutBeginingZero = contactController.text + .replaceAll(" ", "") + .substring(1, contactController.text.length); + } else { + numberWithoutBeginingZero = contactController.text.replaceAll("-", " "); + } + return "${countryCodeController.text}-$numberWithoutBeginingZero"; + } + + bool isFormFilled() { + if (typeController.text.isEmpty) { + return false; + } else { + return true; + } + } + + void successPopUp(String message, bool stayOnPersonalSide) { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.check_circle_outline_rounded, + size: 150, + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: "Successfully Updated Profile", + alertBody: Column( + children: [ + Text( + message, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + context.pop(); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Dismiss", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + // return MIHSuccessMessage( + // successType: "Success", + // successMessage: message, + // ); + }, + ); + } + + Future uploadFile(MzansiProfileProvider mzansiProfileProvider) async { + if (newSelectedLogoPic != null) { + int uploadStatusCode = 0; + uploadStatusCode = await MihFileApi.uploadFile( + mzansiProfileProvider.business!.business_id, + env, + "business_files", + newSelectedLogoPic!, + context, + ); + if (uploadStatusCode == 200) { + int deleteStatusCode = 0; + deleteStatusCode = await MihFileApi.deleteFile( + mzansiProfileProvider.business!.logo_path.split("/").first, + env, + "business_files", + mzansiProfileProvider.business!.logo_path.split("/").last, + context, + ); + if (deleteStatusCode == 200) { + return true; + } else { + return false; + } + } else { + return false; + } + } else { + return true; // No file selected, so no upload needed + } + } + + Future submitForm(MzansiProfileProvider mzansiProfileProvider) async { + KenLogger.success("Start Submit Form"); + if (isFormFilled()) { + KenLogger.success("Form Filled"); + KenLogger.success("Start File Upload"); + bool successfullyUploadedFile = await uploadFile(mzansiProfileProvider); + KenLogger.success( + "File Upload Complete: outcome $successfullyUploadedFile"); + if (!mounted) return; + KenLogger.success("is mounted"); + if (successfullyUploadedFile) { + KenLogger.success("Start Details Update"); + int statusCode = 0; + statusCode = await MihBusinessDetailsServices().updateBusinessDetailsV2( + mzansiProfileProvider.business!.business_id, + nameController.text, + typeController.text, + regController.text, + practiceNoController.text, + vatNoController.text, + emailController.text, + getNumberWithCountryCode(), + // contactController.text, + locationController.text, + fileNameController.text, + websiteController.text, + ratingController.text.isEmpty ? "0" : ratingController.text, + missionVisionController.text, + mzansiProfileProvider, + context, + ); + KenLogger.success("Details Update Complete: status code $statusCode"); + if (!mounted) return; + KenLogger.success("is mounted"); + if (statusCode == 200) { + KenLogger.success("Start Success Message"); + //You left of here + String message = "Your information has been updated successfully!"; + context.pop(); + successPopUp(message, false); + // File uploaded successfully + } else { + context.pop(); + // File upload failed + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.warning_rounded, + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: "Error Updating Business Details", + alertBody: Column( + children: [ + Text( + "An error occurred while updating the business details. Please check internet connection and try again.", + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ], + ), + alertColour: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + ); + } + } else { + context.pop(); + if (!mounted) return; + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Internet Connection"); + }, + ); + } + } else { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Input Error"); + }, + ); + } + } + + @override + void initState() { + super.initState(); + setControllers(); + missionVisionController.addListener(_updateMissionVisionCounter); + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return MihPackageWindow( + fullscreen: false, + windowTitle: 'Edit Profile', + onWindowTapClose: () { + context.pop(); + }, + windowBody: MihSingleChildScroll( + child: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: widget.width * 0.05) + : EdgeInsets.symmetric(horizontal: widget.width * 0), + child: Column( + children: [ + MihForm( + formKey: _formKey, + formFields: [ + Center( + child: MihCircleAvatar( + imageFile: newSelectedLogoPic != null + ? MemoryImage(newSelectedLogoPic!.bytes!) + : mzansiProfileProvider.businessProfilePicture, + width: 150, + editable: true, + fileNameController: fileNameController, + userSelectedfile: newSelectedLogoPic, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: (selectedfile) { + setState(() { + newSelectedLogoPic = selectedfile; + }); + }, + ), + ), + Visibility( + visible: false, + child: MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: fileNameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Selected File Name", + ), + ), + const SizedBox(height: 20), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: nameController, + multiLineInput: false, + requiredText: true, + hintText: "Business Name", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: typeController, + multiLineInput: false, + requiredText: true, + hintText: "Business Type", + validator: (value) { + return MihValidationServices() + .validateNoSpecialChars(value); + }, + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: emailController, + multiLineInput: false, + requiredText: true, + hintText: "Business Email", + validator: (value) { + return MihValidationServices().validateEmail(value); + }, + ), + const SizedBox(height: 10), + Container( + width: 300, + alignment: Alignment.topLeft, + child: const Text( + "Contact Number:", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + CountryCodePicker( + padding: EdgeInsetsGeometry.all(0), + onChanged: (selectedCode) { + setState(() { + countryCodeController.text = + selectedCode.toString(); + }); + debugPrint( + "Selected Country Code: ${countryCodeController.text}"); + }, + initialSelection: countryCodeController.text, + showDropDownButton: false, + pickerStyle: PickerStyle.bottomSheet, + dialogBackgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + barrierColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + Expanded( + child: MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: contactController, + numberMode: true, + multiLineInput: false, + requiredText: true, + hintText: null, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + ), + ], + ), + const SizedBox(height: 10), + MihTextFormField( + height: 250, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: missionVisionController, + multiLineInput: true, + requiredText: true, + hintText: "Business Mission & Vision", + validator: (value) { + return MihValidationServices().validateLength( + missionVisionController.text, 256); + }, + ), + SizedBox( + height: 15, + child: ValueListenableBuilder( + valueListenable: _counter, + builder: + (BuildContext context, int value, Widget? child) { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "$value", + style: TextStyle( + color: getMissionVisionLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 5), + Text( + "/256", + style: TextStyle( + color: getMissionVisionLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + ], + ); + }, + ), + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: websiteController, + multiLineInput: false, + requiredText: false, + hintText: "Business Website", + validator: (value) { + return MihValidationServices() + .validateWebsite(value, false); + }, + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: regController, + multiLineInput: false, + requiredText: false, + hintText: "Registration No.", + validator: (value) { + // return MihValidationServices().isEmpty(value); + return null; + }, + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: practiceNoController, + multiLineInput: false, + requiredText: false, + hintText: "Practice Number", + validator: (validateValue) { + return null; + }, + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: vatNoController, + multiLineInput: false, + requiredText: false, + hintText: "VAT Number", + validator: (value) { + // return MihValidationServices().isEmpty(value); + return null; + }, + ), + const SizedBox(height: 10), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Flexible( + child: MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: locationController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "GPS Location", + ), + ), + const SizedBox(width: 10.0), + MihButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle( + message: "Getting your location", + ); + }, + ); + MIHLocationAPI() + .getGPSPosition(context) + .then((position) { + if (position != null) { + setState(() { + locationController.text = + "${position.latitude}, ${position.longitude}"; + }); + } + //Dismiss loading indicator + context.pop(); + }); + }, + buttonColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 100, + child: Text( + "Set", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + submitForm(mzansiProfileProvider); + } else { + MihAlertServices() + .formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Update", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + const SizedBox(height: 20), + ], + ), + ], + ), + ), + ), + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart index f106ec95..69dd98ea 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart @@ -1,23 +1,20 @@ import 'package:go_router/go_router.dart'; -import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart'; -import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart'; +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_team.dart'; -import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_user.dart'; +import 'package:provider/provider.dart'; class MzansiBusinessProfile extends StatefulWidget { - final BusinessArguments arguments; const MzansiBusinessProfile({ super.key, - required this.arguments, }); @override @@ -25,28 +22,6 @@ class MzansiBusinessProfile extends StatefulWidget { } class _MzansiBusinessProfileState extends State { - int _selcetedIndex = 0; - late Future futureLogoUrl; - late Future futureProPicUrl; - late Future futureUserSignatureUrl; - - @override - void initState() { - super.initState(); - futureLogoUrl = MihFileApi.getMinioFileUrl( - widget.arguments.business!.logo_path, - context, - ); - futureProPicUrl = MihFileApi.getMinioFileUrl( - widget.arguments.signedInUser.pro_pic_path, - context, - ); - futureUserSignatureUrl = MihFileApi.getMinioFileUrl( - widget.arguments.businessUser!.sig_path, - context, - ); - } - @override Widget build(BuildContext context) { return MihPackage( @@ -54,11 +29,9 @@ class _MzansiBusinessProfileState extends State { appTools: getTools(), appBody: getToolBody(), appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); + selectedbodyIndex: context.watch().businessIndex, + onIndexChange: (newIndex) { + context.read().setBusinessIndex(newIndex); }, ); } @@ -70,9 +43,9 @@ class _MzansiBusinessProfileState extends State { onTap: () { context.goNamed( 'mihHome', - extra: false, ); FocusScope.of(context).unfocus(); + context.read().setBusinessIndex(0); }, ); } @@ -80,95 +53,43 @@ class _MzansiBusinessProfileState extends State { MihPackageTools getTools() { Map temp = {}; temp[const Icon(Icons.business)] = () { - setState(() { - _selcetedIndex = 0; - }); + context.read().setBusinessIndex(0); }; temp[const Icon(Icons.person)] = () { - setState(() { - _selcetedIndex = 1; - }); + context.read().setBusinessIndex(1); }; - // temp[const Icon(Icons.warning)] = () { - // setState(() { - // _selcetedIndex = 2; - // }); - // }; temp[const Icon(Icons.people)] = () { - setState(() { - _selcetedIndex = 2; - }); + context.read().setBusinessIndex(2); }; temp[const Icon(Icons.add)] = () { - setState(() { - _selcetedIndex = 3; - }); + context + .read() + .setUserearchResults(userSearchResults: []); + context.read().setBusinessIndex(3); }; temp[const Icon(Icons.star_rate_rounded)] = () { - setState(() { - _selcetedIndex = 4; - }); + context.read().setBusinessIndex(4); }; temp[const Icon(Icons.qr_code_rounded)] = () { - setState(() { - _selcetedIndex = 5; - }); + context.read().setBusinessIndex(5); }; return MihPackageTools( tools: temp, - selcetedIndex: _selcetedIndex, + selcetedIndex: context.watch().businessIndex, ); } List getToolBody() { List toolBodies = [ - FutureBuilder( - future: futureLogoUrl, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center(child: Mihloadingcircle()); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - final logoUrl = snapshot.data!.isNotEmpty - ? NetworkImage(snapshot.data!) - : null; - return MihBusinessDetails( - arguments: widget.arguments, - logoImage: logoUrl, - ); - } else { - return Text("Error: ${snapshot.error}"); - } - }), - FutureBuilder>( - future: Future.wait([futureProPicUrl, futureUserSignatureUrl]), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center(child: Mihloadingcircle()); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - final proPicUrl = NetworkImage(snapshot.data![0]); - print("=============== Signature URL: ${snapshot.data![1]}"); - final signatureUrl = snapshot.data![1].isNotEmpty - ? NetworkImage(snapshot.data![1]) - : null; - return MihMyBusinessUser( - arguments: widget.arguments, - userProPicImage: proPicUrl, - userSignatureImage: signatureUrl, - ); - } else { - return Text("Error: ${snapshot.error}"); - } - }, - ), - // MihBusinessProfile(arguments: widget.arguments), - MihMyBusinessTeam(arguments: widget.arguments), - MihBusinessUserSearch(arguments: widget.arguments), - MihBusinessReviews(business: widget.arguments.business!), + MihBusinessDetails(), + MihMyBusinessUser(), + MihMyBusinessTeam(), + MihBusinessUserSearch(), + MihBusinessReviews( + business: context.watch().business!), MihBusinessQrCode( - business: widget.arguments.business!, - startUpSearch: "", + business: context.watch().business!, + // startUpSearch: "", ), ]; return toolBodies; diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart index 2e625382..21231d4a 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart @@ -1,23 +1,22 @@ import 'package:go_router/go_router.dart'; import 'package:ken_logger/ken_logger.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; +import 'package:provider/provider.dart'; class MzansiBusinessProfileView extends StatefulWidget { - final BusinessViewArguments? arguments; final String? businessId; const MzansiBusinessProfileView({ super.key, - required this.arguments, required this.businessId, }); @@ -28,16 +27,10 @@ class MzansiBusinessProfileView extends StatefulWidget { class _MzansiBusinessProfileViewState extends State { int _selcetedIndex = 0; - Business? business; - String startUpSearch = ""; - Future _fetchBusinessDetails() async { - if (widget.arguments != null) { - setState(() { - business = widget.arguments!.business; - startUpSearch = widget.arguments!.startUpSearch ?? ""; - }); - } else if (widget.businessId != null) { + Future _fetchBusinessDetails( + MzansiDirectoryProvider directoryProvider) async { + if (widget.businessId != null) { final biz = await MihBusinessDetailsServices() .getBusinessDetailsByBusinessId(widget.businessId!); if (biz == null) { @@ -47,10 +40,7 @@ class _MzansiBusinessProfileViewState extends State { ); } else { KenLogger.success("Business found: ${biz.Name}"); - setState(() { - business = biz; - startUpSearch = ""; - }); + directoryProvider.setSelectedBusiness(business: biz); } } } @@ -58,32 +48,39 @@ class _MzansiBusinessProfileViewState extends State { @override void initState() { super.initState(); - _fetchBusinessDetails(); + MzansiDirectoryProvider directoryProvider = + context.read(); + _fetchBusinessDetails(directoryProvider); } @override Widget build(BuildContext context) { - if (business == null) { - KenLogger.warning("Business is null, showing loading indicator"); - return Scaffold( - body: const Center( - child: Mihloadingcircle(), - ), - ); - } else { - return MihPackage( - appActionButton: getAction(), - appTools: getTools(), - appBody: getToolBody(), - appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); - }, - ); - } + return Consumer( + builder: (BuildContext context, MzansiDirectoryProvider directoryProvider, + Widget? child) { + if (directoryProvider.selectedBusiness == null) { + KenLogger.warning("Business is null, showing loading indicator"); + return Scaffold( + body: const Center( + child: Mihloadingcircle(), + ), + ); + } else { + return MihPackage( + appActionButton: getAction(), + appTools: getTools(), + appBody: getToolBody(directoryProvider), + appToolTitles: getToolTitle(), + selectedbodyIndex: _selcetedIndex, + onIndexChange: (newValue) { + setState(() { + _selcetedIndex = newValue; + }); + }, + ); + } + }, + ); } MihPackageAction getAction() { @@ -91,13 +88,18 @@ class _MzansiBusinessProfileViewState extends State { icon: const Icon(Icons.arrow_back), iconSize: 35, onTap: () { - context.goNamed( - "mzansiDirectory", - extra: MzansiDirectoryArguments( - personalSearch: false, - startSearchText: business!.Name, - ), - ); + MzansiProfileProvider profileProvider = + context.read(); + if (profileProvider.user == null) { + context.goNamed( + 'mihHome', + ); + } else { + context.pop(); + } + // context.goNamed( + // "mzansiDirectory", + // ); FocusScope.of(context).unfocus(); }, ); @@ -126,16 +128,12 @@ class _MzansiBusinessProfileViewState extends State { ); } - List getToolBody() { + List getToolBody(MzansiDirectoryProvider directoryProvider) { List toolBodies = [ - MihBusinessDetailsView( - business: business!, - startUpSearch: startUpSearch, - ), - MihBusinessReviews(business: business!), + MihBusinessDetailsView(), + MihBusinessReviews(business: directoryProvider.selectedBusiness!), MihBusinessQrCode( - business: business!, - startUpSearch: startUpSearch, + business: directoryProvider.selectedBusiness!, ) ]; return toolBodies; diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_set_up_business_profile.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_set_up_business_profile.dart new file mode 100644 index 00000000..4449a393 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_set_up_business_profile.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_set_up.dart'; +import 'package:provider/provider.dart'; + +class MzansiSetUpBusinessProfile extends StatefulWidget { + const MzansiSetUpBusinessProfile({super.key}); + + @override + State createState() => + _MzansiSetUpBusinessProfileState(); +} + +class _MzansiSetUpBusinessProfileState + extends State { + @override + Widget build(BuildContext context) { + return MihPackage( + appActionButton: getAction(), + appTools: getTools(), + appBody: getToolBody(), + appToolTitles: getToolTitle(), + selectedbodyIndex: context.watch().businessIndex, + onIndexChange: (newIndex) { + context.read().setBusinessIndex(newIndex); + }, + ); + } + + MihPackageAction getAction() { + return MihPackageAction( + icon: const Icon(Icons.arrow_back), + iconSize: 35, + onTap: () { + context.goNamed( + 'mihHome', + ); + FocusScope.of(context).unfocus(); + context.read().setBusinessIndex(0); + }, + ); + } + + MihPackageTools getTools() { + Map temp = {}; + temp[const Icon(Icons.business)] = () { + context.read().setBusinessIndex(0); + }; + return MihPackageTools( + tools: temp, + selcetedIndex: context.watch().businessIndex, + ); + } + + List getToolTitle() { + List toolTitles = [ + "Set Up Profile", + ]; + return toolTitles; + } + + List getToolBody() { + List toolBodies = [ + MihBusinessDetailsSetUp(), + ]; + return toolBodies; + } +} diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart index abd349c7..96d782bf 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart @@ -2,16 +2,13 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; class MzansiBusinessProfileTile extends StatefulWidget { - final BusinessArguments arguments; final double packageSize; const MzansiBusinessProfileTile({ super.key, - required this.arguments, required this.packageSize, }); @@ -27,7 +24,6 @@ class _MzansiBusinessProfileTileState extends State { onTap: () { context.goNamed( "businessProfileManage", - extra: widget.arguments, ); // Navigator.of(context).pushNamed( // '/business-profile/manage', diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_setup_business_profile_tile.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_setup_business_profile_tile.dart index 268cea2a..4ae9ec40 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_setup_business_profile_tile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_setup_business_profile_tile.dart @@ -2,16 +2,15 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:provider/provider.dart'; class MzansiSetupBusinessProfileTile extends StatefulWidget { - final AppUser signedInUser; final double packageSize; const MzansiSetupBusinessProfileTile({ super.key, - required this.signedInUser, required this.packageSize, }); @@ -24,11 +23,13 @@ class _MzansiSetupBusinessProfileTileState extends State { @override Widget build(BuildContext context) { + MzansiProfileProvider profileProvider = + context.read(); return MihPackageTile( onTap: () { context.goNamed( 'businessProfileSetup', - extra: widget.signedInUser, + extra: profileProvider.user, ); // Navigator.of(context).pushNamed( // '/business-profile/set-up', diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart index 00c22f00..c65a144c 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart @@ -1,35 +1,19 @@ -import 'package:country_code_picker/country_code_picker.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_update_business_details_window.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:provider/provider.dart'; class MihBusinessDetails extends StatefulWidget { - final BusinessArguments arguments; - final ImageProvider? logoImage; const MihBusinessDetails({ super.key, - required this.arguments, - required this.logoImage, }); @override @@ -37,695 +21,25 @@ class MihBusinessDetails extends StatefulWidget { } class _MihBusinessDetailsState extends State { - PlatformFile? imageFile; + PlatformFile? newSelectedLogoPic; final fileNameController = TextEditingController(); - final regController = TextEditingController(); - final nameController = TextEditingController(); - final typeController = TextEditingController(); - final practiceNoController = TextEditingController(); - final vatNoController = TextEditingController(); - final countryCodeController = TextEditingController(); - final contactController = TextEditingController(); - final emailController = TextEditingController(); - final locationController = TextEditingController(); - final websiteController = TextEditingController(); - final ratingController = TextEditingController(); - final missionVisionController = TextEditingController(); - final _formKey = GlobalKey(); - final ValueNotifier _counter = ValueNotifier(0); - late String env; - void successPopUp(String message, bool stayOnPersonalSide) { + void editBizProfileWindow( + MzansiProfileProvider mzansiProfileProvider, double width) { showDialog( context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.check_circle_outline_rounded, - size: 150, - color: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: "Successfully Updated Profile", - alertBody: Column( - children: [ - Text( - message, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 15, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 25), - Center( - child: MihButton( - onPressed: () { - context.goNamed( - 'mihHome', - extra: stayOnPersonalSide, - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - elevation: 10, - width: 300, - child: Text( - "Dismiss", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ) - ], - ), - alertColour: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - // return MIHSuccessMessage( - // successType: "Success", - // successMessage: message, - // ); - }, + builder: (context) => MihUpdateBusinessDetailsWindow(width: width), ); } - Future submitForm() async { - if (isFormFilled()) { - int statusCode = 0; - statusCode = await MihBusinessDetailsServices().updateBusinessDetailsV2( - widget.arguments.business!.business_id, - nameController.text, - typeController.text, - regController.text, - practiceNoController.text, - vatNoController.text, - emailController.text, - getNumberWithCountryCode(), - // contactController.text, - locationController.text, - fileNameController.text, - websiteController.text, - ratingController.text.isEmpty ? "0" : ratingController.text, - missionVisionController.text, - context, - ); - if (statusCode == 200) { - bool successfullyUploadedFile = await uploadFile(); - if (successfullyUploadedFile) { - //You left of here - String message = "Your information has been updated successfully!"; - successPopUp(message, false); - // File uploaded successfully - } else { - // File upload failed - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.warning_rounded, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: "Error Updating Business Details", - alertBody: Column( - children: [ - Text( - "An error occurred while updating the business details. Please check internet connection and try again.", - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - ], - ), - alertColour: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - }, - ); - } - } else { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); - } - } else { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Input Error"); - }, - ); - } - } - - Future uploadFile() async { - if (imageFile != null) { - int uploadStatusCode = 0; - uploadStatusCode = await MihFileApi.uploadFile( - widget.arguments.business!.business_id, - env, - "business_files", - imageFile!, - context, - ); - if (uploadStatusCode == 200) { - int deleteStatusCode = 0; - deleteStatusCode = await MihFileApi.deleteFile( - widget.arguments.business!.logo_path.split("/").first, - env, - "business_files", - widget.arguments.business!.logo_path.split("/").last, - context, - ); - if (deleteStatusCode == 200) { - return true; - } else { - return false; - } - } else { - return false; - } - } else { - return true; // No file selected, so no upload needed - } - } - - bool isFileSelected() { - if (imageFile != null) { - return true; - } else { - return false; - } - } - - bool isEmailValid() { - String text = emailController.text; - var regex = RegExp(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'); - return regex.hasMatch(text); - } - - bool isFormFilled() { - if (typeController.text.isEmpty) { - return false; - } else { - return true; - } - } - - void setContactNumberControllers() { - if (widget.arguments.business!.contact_no[0] == "+") { - List contactDetails = - widget.arguments.business!.contact_no.split("-"); - setState(() { - countryCodeController.text = contactDetails[0]; - contactController.text = contactDetails[1]; - }); - } else { - setState(() { - countryCodeController.text = "+27"; - contactController.text = widget.arguments.business!.contact_no; - }); - } - } - - String getNumberWithCountryCode() { - String numberWithoutBeginingZero = ""; - if (contactController.text[0] == "0") { - numberWithoutBeginingZero = contactController.text - .replaceAll(" ", "") - .substring(1, contactController.text.length); - } else { - numberWithoutBeginingZero = contactController.text.replaceAll("-", " "); - } - return "${countryCodeController.text}-$numberWithoutBeginingZero"; - } - - void editBizProfileWindow(double width) { - showDialog( - context: context, - builder: (context) => MihPackageWindow( - fullscreen: false, - windowTitle: 'Edit Profile', - onWindowTapClose: () { - context.pop(); - resetControllers(); - }, - windowBody: MihSingleChildScroll( - child: Padding( - padding: MzansiInnovationHub.of(context)!.theme.screenType == - "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.05) - : EdgeInsets.symmetric(horizontal: width * 0), - child: Column( - children: [ - MihForm( - formKey: _formKey, - formFields: [ - Center( - child: MihCircleAvatar( - imageFile: widget.logoImage, - width: 150, - editable: true, - fileNameController: fileNameController, - userSelectedfile: imageFile, - frameColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - backgroundColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - onChange: (selectedfile) { - setState(() { - imageFile = selectedfile; - }); - }, - ), - ), - Visibility( - visible: false, - child: MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: fileNameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Selected File Name", - ), - ), - const SizedBox(height: 20), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: nameController, - multiLineInput: false, - requiredText: true, - hintText: "Business Name", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: typeController, - multiLineInput: false, - requiredText: true, - hintText: "Business Type", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: emailController, - multiLineInput: false, - requiredText: true, - hintText: "Business Email", - validator: (value) { - return MihValidationServices() - .validateEmail(value); - }, - ), - const SizedBox(height: 10), - Container( - width: 300, - alignment: Alignment.topLeft, - child: const Text( - "Contact Number:", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ), - Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - CountryCodePicker( - padding: EdgeInsetsGeometry.all(0), - onChanged: (selectedCode) { - setState(() { - countryCodeController.text = - selectedCode.toString(); - }); - debugPrint( - "Selected Country Code: ${countryCodeController.text}"); - }, - initialSelection: countryCodeController.text, - showDropDownButton: false, - pickerStyle: PickerStyle.bottomSheet, - dialogBackgroundColor: - MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - barrierColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - ), - Expanded( - child: MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - controller: contactController, - numberMode: true, - multiLineInput: false, - requiredText: true, - hintText: null, - validator: (value) { - return MihValidationServices() - .isEmpty(value); - }, - ), - ), - ], - ), - const SizedBox(height: 10), - MihTextFormField( - height: 250, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: missionVisionController, - multiLineInput: true, - requiredText: true, - hintText: "Business Mission & Vision", - validator: (value) { - return MihValidationServices().validateLength( - missionVisionController.text, 256); - }, - ), - SizedBox( - height: 15, - child: ValueListenableBuilder( - valueListenable: _counter, - builder: (BuildContext context, int value, - Widget? child) { - return Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - "$value", - style: TextStyle( - color: getMissionVisionLimitColor(256), - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(width: 5), - Text( - "/256", - style: TextStyle( - color: getMissionVisionLimitColor(256), - fontWeight: FontWeight.bold, - ), - ), - ], - ); - }, - ), - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: websiteController, - multiLineInput: false, - requiredText: false, - hintText: "Business Website", - validator: (value) { - return MihValidationServices() - .validateWebsite(value, false); - }, - ), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: regController, - multiLineInput: false, - requiredText: false, - hintText: "Registration No.", - validator: (value) { - // return MihValidationServices().isEmpty(value); - return null; - }, - ), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: practiceNoController, - multiLineInput: false, - requiredText: false, - hintText: "Practice Number", - validator: (validateValue) { - return null; - }, - ), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: vatNoController, - multiLineInput: false, - requiredText: false, - hintText: "VAT Number", - validator: (value) { - // return MihValidationServices().isEmpty(value); - return null; - }, - ), - const SizedBox(height: 10), - Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Flexible( - child: MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - controller: locationController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "GPS Location", - ), - ), - const SizedBox(width: 10.0), - MihButton( - onPressed: () { - showDialog( - context: context, - builder: (context) { - return const Mihloadingcircle( - message: "Getting your location", - ); - }, - ); - MIHLocationAPI() - .getGPSPosition(context) - .then((position) { - if (position != null) { - setState(() { - locationController.text = - "${position.latitude}, ${position.longitude}"; - }); - } - //Dismiss loading indicator - Navigator.of(context).pop(); - }); - }, - buttonColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - width: 100, - child: Text( - "Set", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - const SizedBox(height: 25), - Center( - child: MihButton( - onPressed: () { - if (_formKey.currentState!.validate()) { - submitForm(); - } else { - MihAlertServices() - .formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - width: 300, - child: Text( - "Update", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - const SizedBox(height: 20), - ], - ), - ], - ), - ), - ), - )); - } - - Color getMissionVisionLimitColor(int limit) { - if (_counter.value <= limit) { - return MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"); - } else { - return MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"); - } - } - - void resetControllers() { - setState(() { - fileNameController.text = - widget.arguments.business!.logo_path.split("/").last; - regController.text = widget.arguments.business!.registration_no; - nameController.text = widget.arguments.business!.Name; - typeController.text = widget.arguments.business!.type; - practiceNoController.text = widget.arguments.business!.practice_no; - vatNoController.text = widget.arguments.business!.vat_no; - emailController.text = widget.arguments.business!.bus_email; - locationController.text = widget.arguments.business!.gps_location; - websiteController.text = widget.arguments.business!.website; - ratingController.text = widget.arguments.business!.rating; - missionVisionController.text = widget.arguments.business!.mission_vision; - }); - setContactNumberControllers(); - if (AppEnviroment.getEnv() == "Prod") { - env = "Prod"; - } else { - env = "Dev"; - } - missionVisionController.addListener(() { - setState(() { - _counter.value = missionVisionController.text.characters.length; - }); - }); - } - @override void dispose() { super.dispose(); - fileNameController.dispose(); - regController.dispose(); - nameController.dispose(); - typeController.dispose(); - practiceNoController.dispose(); - vatNoController.dispose(); - contactController.dispose(); - emailController.dispose(); - locationController.dispose(); - websiteController.dispose(); - ratingController.dispose(); - missionVisionController.dispose(); - imageFile = null; } @override void initState() { super.initState(); - resetControllers(); } @override @@ -739,161 +53,149 @@ class _MihBusinessDetailsState extends State { } Widget getBody(double width, BuildContext context) { - return Stack( - children: [ - MihSingleChildScroll( - child: Padding( - padding: - MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return Stack( + children: [ + MihSingleChildScroll( + child: Padding( + padding: MzansiInnovationHub.of(context)!.theme.screenType == + "desktop" ? EdgeInsets.symmetric(horizontal: width * 0.2) : EdgeInsets.symmetric(horizontal: width * 0.075), - child: Column( - children: [ - Center( - child: MihCircleAvatar( - imageFile: widget.logoImage, - width: 150, - editable: false, - fileNameController: fileNameController, - userSelectedfile: imageFile, - frameColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - backgroundColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onChange: (selectedfile) { - setState(() { - imageFile = selectedfile; - }); - }, - ), - ), - FittedBox( - child: Text( - widget.arguments.business!.Name, - style: TextStyle( - fontSize: 35, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - ), - FittedBox( - child: Text( - widget.arguments.business!.type, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w600, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - ), - const SizedBox(height: 5), - // FittedBox( - // child: Text( - // "Mission & Vision", - // style: TextStyle( - // fontSize: 15, - // fontWeight: FontWeight.bold, - // color: MzansiInnovationHub.of(context)! - // .theme - // .secondaryColor(), - // ), - // ), - // ), - Center( - child: SizedBox( - width: 700, - child: Text( - widget.arguments.business!.mission_vision.isNotEmpty - ? widget.arguments.business!.mission_vision - : "No Mission & Vision added yet", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( + child: Column( + children: [ + Center( + child: MihCircleAvatar( + imageFile: mzansiProfileProvider.businessProfilePicture, + width: 150, + editable: false, + fileNameController: fileNameController, + userSelectedfile: newSelectedLogoPic, + frameColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - ), - ), - const SizedBox(height: 20), - SizedBox( - width: 700, - child: MihBusinessCard( - // businessid: widget.arguments.business!.business_id, - // businessName: widget.arguments.business!.Name, - // cellNumber: widget.arguments.business!.contact_no, - // email: widget.arguments.business!.bus_email, - // gpsLocation: widget.arguments.business!.gps_location, - // rating: widget.arguments.business!.rating.isNotEmpty - // ? double.parse(widget.arguments.business!.rating) - // : 0, - // website: widget.arguments.business!.website, - business: widget.arguments.business!, - startUpSearch: null, - width: width, - ), - ), - const SizedBox(height: 30.0), - Center( - child: MihButton( - onPressed: () { - // Connect with the user - editBizProfileWindow(width); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Text( - "Edit Profile", - style: TextStyle( - color: MihColors.getPrimaryColor( + backgroundColor: MihColors.getPrimaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, + onChange: (selectedfile) { + setState(() { + newSelectedLogoPic = selectedfile; + }); + }, ), ), - ), + FittedBox( + child: Text( + mzansiProfileProvider.business!.Name, + style: TextStyle( + fontSize: 35, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + FittedBox( + child: Text( + mzansiProfileProvider.business!.type, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + const SizedBox(height: 5), + Center( + child: SizedBox( + width: 700, + child: Text( + mzansiProfileProvider + .business!.mission_vision.isNotEmpty + ? mzansiProfileProvider.business!.mission_vision + : "No Mission & Vision added yet", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + ), + const SizedBox(height: 20), + SizedBox( + width: 700, + child: MihBusinessCard( + business: mzansiProfileProvider.business!, + // startUpSearch: null, + width: width, + ), + ), + const SizedBox(height: 30.0), + Center( + child: MihButton( + onPressed: () { + // Connect with the user + editBizProfileWindow(mzansiProfileProvider, width); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Edit Profile", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], ), - ], + ), ), - ), - ), - // Positioned( - // right: 5, - // bottom: 10, - // child: MihFloatingMenu( - // animatedIcon: AnimatedIcons.menu_close, - // children: [ - // SpeedDialChild( - // child: Icon( - // Icons.edit, - // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // label: "Edit Profile", - // labelBackgroundColor: - // MihColors.getGreenColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // labelStyle: TextStyle( - // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // fontWeight: FontWeight.bold, - // ), - // backgroundColor: - // MihColors.getGreenColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // onTap: () { - // editBizProfileWindow(width); - // }, - // ) - // ], - // ), - // ), - ], + // Positioned( + // right: 5, + // bottom: 10, + // child: MihFloatingMenu( + // animatedIcon: AnimatedIcons.menu_close, + // children: [ + // SpeedDialChild( + // child: Icon( + // Icons.edit, + // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + // label: "Edit Profile", + // labelBackgroundColor: + // MihColors.getGreenColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // labelStyle: TextStyle( + // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // fontWeight: FontWeight.bold, + // ), + // backgroundColor: + // MihColors.getGreenColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // onTap: () { + // editBizProfileWindow(width); + // }, + // ) + // ], + // ), + // ), + ], + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_set_up.dart similarity index 81% rename from Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart rename to Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_set_up.dart index 5362dde8..ab37bd22 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_set_up.dart @@ -1,53 +1,43 @@ -import 'dart:convert'; - import 'package:country_code_picker/country_code_picker.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; import 'package:http/http.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_image_display.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +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_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_my_business_user_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; -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_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:file_picker/file_picker.dart'; +import 'package:provider/provider.dart'; -class ProfileBusinessAdd extends StatefulWidget { - //final BusinessUserScreenArguments arguments; - final AppUser signedInUser; - const ProfileBusinessAdd({ - super.key, - required this.signedInUser, - }); +class MihBusinessDetailsSetUp extends StatefulWidget { + const MihBusinessDetailsSetUp({super.key}); @override - State createState() => _ProfileBusinessAddState(); + State createState() => + _MihBusinessDetailsSetUpState(); } -class _ProfileBusinessAddState extends State { - final FocusNode _focusNode = FocusNode(); - final baseAPI = AppEnviroment.baseApiUrl; - +class _MihBusinessDetailsSetUpState extends State { final nameController = TextEditingController(); final typeController = TextEditingController(); final regController = TextEditingController(); final addressController = TextEditingController(); - final logonameController = TextEditingController(); final fnameController = TextEditingController(); final lnameController = TextEditingController(); final titleController = TextEditingController(); @@ -62,65 +52,33 @@ class _ProfileBusinessAddState extends State { final websiteController = TextEditingController(); final ratingController = TextEditingController(); final missionVisionController = TextEditingController(); - - ImageProvider? logoPreview; - ImageProvider? signaturePreview; - PlatformFile? selectedLogo; - PlatformFile? selectedSignature; - + final logoFileNameController = TextEditingController(); + PlatformFile? newSelectedLogoPic; + PlatformFile? newSelectedSignaturePic; + final FocusNode _focusNode = FocusNode(); + final _formKey = GlobalKey(); final ValueNotifier _counter = ValueNotifier(0); final ValueNotifier busType = ValueNotifier(""); - final _formKey = GlobalKey(); late String env; - Future uploadFile(String id, PlatformFile? selectedFile) async { - print("Inside uploud file method"); - int uploadStatusCode = 0; - uploadStatusCode = await MihFileApi.uploadFile( - id, - env, - "business_files", - selectedFile, - context, - ); - print("Status code: $uploadStatusCode"); - if (uploadStatusCode == 200) { - return true; + void submitForm(MzansiProfileProvider mzansiProfileProvider) { + if (isFieldsFilled()) { + createBusinessProfileAPICall(mzansiProfileProvider); } else { - return false; + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Input Error"); + }, + ); } } - Future createBusinessUserAPICall(String business_id) async { - print("Inside create bus user method"); - int statusCode = await MihMyBusinessUserServices().createBusinessUser( - business_id, - widget.signedInUser.app_id, - signtureController.text, - titleController.text, - accessController.text, - context, - ); - print("Status code: $statusCode"); - if (statusCode == 201) { - // Navigator.of(context).pop(); - // Navigator.of(context).popAndPushNamed( - // '/', - // arguments: AuthArguments(false, false), - // ); - String message = - "Your business profile is now live! You can now start connecting with customers and growing your business."; - successPopUp(message, false); - } else { - internetConnectionPopUp(); - } - } - - Future createBusinessProfileAPICall() async { - print("Inside create business profile method"); + Future createBusinessProfileAPICall( + MzansiProfileProvider mzansiProfileProvider) async { Response response = await MihBusinessDetailsServices().createBusinessDetails( - widget.signedInUser.app_id, + mzansiProfileProvider, nameController.text, typeController.text, regController.text, @@ -128,23 +86,87 @@ class _ProfileBusinessAddState extends State { vatNoController.text, emailController.text, getNumberWithCountryCode(), - // "${countryCodeController.text}-${contactController.text}", locationController.text, - logonameController.text, + logoFileNameController.text, websiteController.text, "0", missionVisionController.text, context, ); - print(response.body); if (response.statusCode == 201) { - var businessResponse = jsonDecode(response.body); - createBusinessUserAPICall(businessResponse['business_id']); + bool successUpload = + await uploadFile(mzansiProfileProvider, newSelectedLogoPic); + if (successUpload) { + String logoUrl = await MihFileApi.getMinioFileUrl( + mzansiProfileProvider.business!.logo_path, context); + mzansiProfileProvider.setBusinessProfilePicUrl(logoUrl); + } + await createBusinessUserAPICall(mzansiProfileProvider); } else { internetConnectionPopUp(); } } + Future createBusinessUserAPICall( + MzansiProfileProvider mzansiProfileProvider) async { + int statusCode = await MihMyBusinessUserServices().createBusinessUser( + mzansiProfileProvider.business!.business_id, + mzansiProfileProvider.user!.app_id, + signtureController.text, + titleController.text, + accessController.text, + mzansiProfileProvider, + context, + ); + if (statusCode == 201) { + bool successUpload = + await uploadFile(mzansiProfileProvider, newSelectedSignaturePic); + if (successUpload) { + String sigUrl = await MihFileApi.getMinioFileUrl( + mzansiProfileProvider.businessUser!.sig_path, context); + mzansiProfileProvider.setBusinessUserSignatureUrl(sigUrl); + String message = + "Your business profile is now live! You can now start connecting with customers and growing your business."; + successPopUp(message, false); + } else { + internetConnectionPopUp(); + } + } else { + internetConnectionPopUp(); + } + } + + Future uploadFile( + MzansiProfileProvider mzansiProfileProvider, PlatformFile? image) async { + if (newSelectedLogoPic != null) { + int uploadStatusCode = 0; + uploadStatusCode = await MihFileApi.uploadFile( + mzansiProfileProvider.business!.business_id, + env, + "business_files", + image, + context, + ); + if (uploadStatusCode == 200) { + return true; + } else { + return false; + } + } else { + return true; // No file selected, so no upload needed + } + } + + bool isFieldsFilled() { + if (typeController.text.isEmpty || + titleController.text.isEmpty || + accessController.text.isEmpty) { + return false; + } else { + return true; + } + } + String getNumberWithCountryCode() { String numberWithoutBeginingZero = ""; if (contactController.text[0] == "0") { @@ -157,13 +179,22 @@ class _ProfileBusinessAddState extends State { return "${countryCodeController.text}-$numberWithoutBeginingZero"; } - void internetConnectionPopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); + Color getMissionVisionLimitColor(int limit) { + if (_counter.value <= limit) { + return MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } else { + return MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } + } + + void typeSelected() { + if (typeController.text.isNotEmpty) { + busType.value = typeController.text; + } else { + busType.value = ""; + } } void successPopUp(String message, bool stayOnPersonalSide) { @@ -227,110 +258,90 @@ class _ProfileBusinessAddState extends State { ); } - bool isFieldsFilled() { - if (typeController.text.isEmpty || - titleController.text.isEmpty || - accessController.text.isEmpty) { - return false; - } else { - return true; - } - } - - void submitForm() { - if (isFieldsFilled()) { - print("Inside submit method"); - createBusinessProfileAPICall(); - } else { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Input Error"); - }, - ); - } - } - - void emailError() { + void internetConnectionPopUp() { showDialog( context: context, builder: (context) { - return const MIHErrorMessage(errorType: "Invalid Email"); + return const MIHErrorMessage(errorType: "Internet Connection"); }, ); } - bool isEmailValid() { - String text = emailController.text; - var regex = RegExp(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'); - return regex.hasMatch(text); - } - - // bool validEmail() { - // String text = emailController.text; - // var regex = RegExp(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'); - // return regex.hasMatch(text); - // } - - void typeSelected() { - if (typeController.text.isNotEmpty) { - busType.value = typeController.text; + void initialiseControlers(MzansiProfileProvider mzansiProfileProvider) { + typeController.addListener(typeSelected); + setState(() { + fnameController.text = mzansiProfileProvider.user!.fname; + lnameController.text = mzansiProfileProvider.user!.lname; + accessController.text = "Full"; + countryCodeController.text = "+27"; + }); + if (AppEnviroment.getEnv() == "Prod") { + env = "Prod"; } else { - busType.value = ""; + env = "Dev"; } + missionVisionController.addListener(() { + setState(() { + _counter.value = missionVisionController.text.characters.length; + }); + }); } - MIHAction getActionButton() { - return MIHAction( - icon: const Icon(Icons.arrow_back), - iconSize: 35, - onTap: () { - // Navigator.of(context).pop(); - context.goNamed( - 'mihHome', - extra: true, - ); - }, - ); + @override + void dispose() { + typeController.removeListener(typeSelected); + nameController.dispose(); + typeController.dispose(); + regController.dispose(); + addressController.dispose(); + fnameController.dispose(); + lnameController.dispose(); + titleController.dispose(); + signtureController.dispose(); + accessController.dispose(); + countryCodeController.dispose(); + contactController.dispose(); + emailController.dispose(); + locationController.dispose(); + practiceNoController.dispose(); + vatNoController.dispose(); + websiteController.dispose(); + ratingController.dispose(); + missionVisionController.dispose(); + logoFileNameController.dispose(); + busType.dispose(); + _focusNode.dispose(); + _counter.dispose(); + super.dispose(); } - MIHHeader getHeader() { - return const MIHHeader( - headerAlignment: MainAxisAlignment.center, - headerItems: [ - Text( - "Set Up Business Profile", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 25, - ), - ), - ], - ); + @override + void initState() { + super.initState(); + initialiseControlers(context.read()); } - Color getMissionVisionLimitColor(int limit) { - if (_counter.value <= limit) { - return MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"); - } else { - return MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"); - } - } - - MIHBody getBody(double width) { - return MIHBody( + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return MihPackageToolBody( borderOn: false, - bodyItems: [ - KeyboardListener( + bodyItem: getBody(screenWidth), + ); + } + + Widget getBody(double width) { + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return KeyboardListener( focusNode: _focusNode, autofocus: true, onKeyEvent: (event) async { if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.enter) { if (_formKey.currentState!.validate()) { - submitForm(); + submitForm(mzansiProfileProvider); } else { MihAlertServices().formNotFilledCompletely(context); } @@ -345,7 +356,7 @@ class _ProfileBusinessAddState extends State { child: Column( children: [ const Text( - "My Business Details", + "Business Details", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 25, @@ -359,6 +370,29 @@ class _ProfileBusinessAddState extends State { MihForm( formKey: _formKey, formFields: [ + Center( + child: MihCircleAvatar( + imageFile: newSelectedLogoPic != null + ? MemoryImage(newSelectedLogoPic!.bytes!) + : mzansiProfileProvider.businessProfilePicture, + width: 150, + editable: true, + fileNameController: logoFileNameController, + userSelectedfile: newSelectedLogoPic, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: (selectedfile) { + setState(() { + newSelectedLogoPic = selectedfile; + }); + }, + ), + ), + const SizedBox(height: 20), MihTextFormField( fillColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == @@ -387,7 +421,8 @@ class _ProfileBusinessAddState extends State { requiredText: true, hintText: "Business Type", validator: (value) { - return MihValidationServices().isEmpty(value); + return MihValidationServices() + .validateNoSpecialChars(value); }, ), const SizedBox(height: 10.0), @@ -643,7 +678,7 @@ class _ProfileBusinessAddState extends State { //const SizedBox(height: 15.0), const Center( child: Text( - "My Business User", + "Business User", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 22, @@ -715,7 +750,7 @@ class _ProfileBusinessAddState extends State { return MihValidationServices().isEmpty(value); }, ), - const SizedBox(height: 15.0), + const SizedBox(height: 10.0), MihTextFormField( fillColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == @@ -732,23 +767,41 @@ class _ProfileBusinessAddState extends State { return MihValidationServices().isEmpty(value); }, ), - // MihDropdownField( - // controller: accessController, - // hintText: "Access Type", - // dropdownOptions: const ["Full", "Partial"], - // editable: false, - // enableSearch: true, - // validator: (value) { - // return MihValidationServices().isEmpty(value); - // }, - // requiredText: true, - // ), + const SizedBox(height: 10), + Container( + width: 300, + alignment: Alignment.topLeft, + child: const Text( + "Signature:", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + Center( + child: MihImageDisplay( + imageFile: newSelectedSignaturePic != null + ? MemoryImage(newSelectedSignaturePic!.bytes!) + : mzansiProfileProvider.businessUserSignature, + width: 300, + height: 200, + editable: true, + fileNameController: signtureController, + userSelectedfile: newSelectedSignaturePic, + onChange: (selectedFile) { + setState(() { + newSelectedSignaturePic = selectedFile; + }); + }, + ), + ), const SizedBox(height: 20.0), Center( child: MihButton( onPressed: () { if (_formKey.currentState!.validate()) { - submitForm(); + submitForm(mzansiProfileProvider); } else { MihAlertServices() .formNotFilledCompletely(context); @@ -770,72 +823,15 @@ class _ProfileBusinessAddState extends State { ), ), ), + const SizedBox(height: 30), ], ), ], ), ), ), - ), - ], - ); - } - - @override - void dispose() { - nameController.dispose(); - typeController.dispose(); - regController.dispose(); - logonameController.dispose(); - fnameController.dispose(); - lnameController.dispose(); - titleController.dispose(); - signtureController.dispose(); - accessController.dispose(); - contactController.dispose(); - emailController.dispose(); - locationController.dispose(); - practiceNoController.dispose(); - vatNoController.dispose(); - _focusNode.dispose(); - super.dispose(); - } - - @override - void initState() { - super.initState(); - typeController.addListener(typeSelected); - setState(() { - fnameController.text = widget.signedInUser.fname; - lnameController.text = widget.signedInUser.lname; - accessController.text = "Full"; - countryCodeController.text = "+27"; - }); - if (AppEnviroment.getEnv() == "Prod") { - env = "Prod"; - } else { - env = "Dev"; - } - missionVisionController.addListener(() { - setState(() { - _counter.value = missionVisionController.text.characters.length; - }); - }); - } - - @override - Widget build(BuildContext context) { - double screenWidth = MediaQuery.of(context).size.width; - return MIHLayoutBuilder( - actionButton: getActionButton(), - secondaryActionButton: null, - header: getHeader(), - body: getBody(screenWidth), - actionDrawer: null, - secondaryActionDrawer: null, - bottomNavBar: null, - pullDownToRefresh: false, - onPullDown: () async {}, + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart index d2f064b1..1a379b81 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart @@ -2,22 +2,19 @@ import 'package:custom_rating_bar/custom_rating_bar.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:provider/provider.dart'; class MihBusinessDetailsView extends StatefulWidget { - final Business business; - final String? startUpSearch; const MihBusinessDetailsView({ super.key, - required this.business, - required this.startUpSearch, }); @override @@ -36,8 +33,10 @@ class _MihBusinessDetailsViewState extends State { @override void initState() { super.initState(); - futureImageUrl = - MihFileApi.getMinioFileUrl(widget.business.logo_path, context); + MzansiDirectoryProvider directoryProvider = + context.read(); + futureImageUrl = MihFileApi.getMinioFileUrl( + directoryProvider.selectedBusiness!.logo_path, context); } @override @@ -52,173 +51,182 @@ class _MihBusinessDetailsViewState extends State { Widget getBody(double width, BuildContext context) { double profilePictureWidth = 150; - return Stack( - children: [ - MihSingleChildScroll( - child: Padding( - padding: - MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + return Consumer( + builder: (BuildContext context, MzansiDirectoryProvider directoryProvider, + Widget? child) { + return Stack( + children: [ + MihSingleChildScroll( + child: Padding( + padding: MzansiInnovationHub.of(context)!.theme.screenType == + "desktop" ? EdgeInsets.symmetric(horizontal: width * 0.2) : EdgeInsets.symmetric(horizontal: width * 0.075), - child: Column( - children: [ - FutureBuilder( - future: futureImageUrl, - builder: (context, asyncSnapshot) { - if (asyncSnapshot.connectionState == - ConnectionState.done && - asyncSnapshot.hasData) { - if (asyncSnapshot.requireData != "") { - return MihCircleAvatar( - imageFile: NetworkImage(asyncSnapshot.requireData), - width: profilePictureWidth, - editable: false, - fileNameController: TextEditingController(), - userSelectedfile: file, - frameColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - backgroundColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - onChange: () {}, - ); - } else { - return Icon( - MihIcons.iDontKnow, - size: profilePictureWidth, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ); - } - } else { - return Icon( - MihIcons.mihRing, - size: profilePictureWidth, + child: Column( + children: [ + FutureBuilder( + future: futureImageUrl, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == + ConnectionState.done && + asyncSnapshot.hasData) { + if (asyncSnapshot.requireData != "") { + return MihCircleAvatar( + imageFile: + NetworkImage(asyncSnapshot.requireData), + width: profilePictureWidth, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.iDontKnow, + size: profilePictureWidth, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ); + } + } else { + return Icon( + MihIcons.mihRing, + size: profilePictureWidth, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ); + } + }), + // Center( + // child: MihCircleAvatar( + // imageFile: widget.logoImage, + // width: 150, + // editable: false, + // fileNameController: fileNameController, + // userSelectedfile: imageFile, + // frameColor: + // MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // backgroundColor: + // MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // onChange: (selectedfile) { + // setState(() { + // imageFile = selectedfile; + // }); + // }, + // ), + // ), + FittedBox( + child: Text( + directoryProvider.selectedBusiness!.Name, + style: TextStyle( + fontSize: 35, + fontWeight: FontWeight.bold, color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - } - }), - // Center( - // child: MihCircleAvatar( - // imageFile: widget.logoImage, - // width: 150, - // editable: false, - // fileNameController: fileNameController, - // userSelectedfile: imageFile, - // frameColor: - // MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // backgroundColor: - // MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // onChange: (selectedfile) { - // setState(() { - // imageFile = selectedfile; - // }); - // }, - // ), - // ), - FittedBox( - child: Text( - widget.business.Name, - style: TextStyle( - fontSize: 35, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - ), - FittedBox( - child: Text( - widget.business.type, - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.w600, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - ), - const SizedBox(height: 5), - // FittedBox( - // child: Text( - // "Mission & Vision", - // style: TextStyle( - // fontSize: 15, - // fontWeight: FontWeight.bold, - // color: MzansiInnovationHub.of(context)! - // .theme - // .secondaryColor(), - // ), - // ), - // ), - Center( - child: SizedBox( - width: 700, - child: Text( - widget.business.mission_vision.isNotEmpty - ? widget.business.mission_vision - : "No Mission & Vision added yet", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), + ), ), ), - ), + FittedBox( + child: Text( + directoryProvider.selectedBusiness!.type, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + const SizedBox(height: 5), + // FittedBox( + // child: Text( + // "Mission & Vision", + // style: TextStyle( + // fontSize: 15, + // fontWeight: FontWeight.bold, + // color: MzansiInnovationHub.of(context)! + // .theme + // .secondaryColor(), + // ), + // ), + // ), + Center( + child: SizedBox( + width: 700, + child: Text( + directoryProvider + .selectedBusiness!.mission_vision.isNotEmpty + ? directoryProvider + .selectedBusiness!.mission_vision + : "No Mission & Vision added yet", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + ), + const SizedBox(height: 10), + RatingBar.readOnly( + size: 50, + alignment: Alignment.center, + filledIcon: Icons.star, + emptyIcon: Icons.star_border, + halfFilledIcon: Icons.star_half, + filledColor: MihColors.getYellowColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + // MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + emptyColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + halfFilledColor: MihColors.getYellowColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + // MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + isHalfAllowed: true, + initialRating: + directoryProvider.selectedBusiness!.rating.isNotEmpty + ? double.parse( + directoryProvider.selectedBusiness!.rating) + : 0, + maxRating: 5, + ), + const SizedBox(height: 20), + SizedBox( + width: 700, + child: MihBusinessCard( + business: directoryProvider.selectedBusiness!, + width: width, + ), + ), + ], ), - const SizedBox(height: 10), - RatingBar.readOnly( - size: 50, - alignment: Alignment.center, - filledIcon: Icons.star, - emptyIcon: Icons.star_border, - halfFilledIcon: Icons.star_half, - filledColor: MihColors.getYellowColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - emptyColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - halfFilledColor: MihColors.getYellowColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - isHalfAllowed: true, - initialRating: widget.business.rating.isNotEmpty - ? double.parse(widget.business.rating) - : 0, - maxRating: 5, - ), - const SizedBox(height: 20), - SizedBox( - width: 700, - child: MihBusinessCard( - business: widget.business, - startUpSearch: widget.startUpSearch, - // businessid: widget.business.business_id, - // businessName: widget.business.Name, - // cellNumber: widget.business.contact_no, - // email: widget.business.bus_email, - // gpsLocation: widget.business.gps_location, - // rating: widget.business.rating.isNotEmpty - // ? double.parse(widget.business.rating) - // : 0, - // website: widget.business.website, - width: width, - ), - ), - ], + ), ), - ), - ), - ], + ], + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart index 4f1b34d9..268c768f 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart @@ -1,4 +1,3 @@ -import 'dart:typed_data'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:file_picker/file_picker.dart'; import 'package:file_saver/file_saver.dart'; @@ -21,15 +20,16 @@ import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; import 'package:screenshot/screenshot.dart'; +import 'package:share_plus/share_plus.dart'; import 'package:supertokens_flutter/supertokens.dart'; class MihBusinessQrCode extends StatefulWidget { final Business business; - final String? startUpSearch; + // final String? startUpSearch; const MihBusinessQrCode({ super.key, required this.business, - required this.startUpSearch, + // required this.startUpSearch, }); @override @@ -89,43 +89,6 @@ class _MihBusinessQrCodeState extends State { mimeType: MimeType.png, ); } - // if (kIsWeb) { - // final blob = html.Blob([imageBytes]); - // final url = html.Url.createObjectUrlFromBlob(blob); - // final anchor = html.document.createElement('a') as html.AnchorElement - // ..href = url - // ..style.display = 'none' - // ..download = filename; // Suggested filename for the download - - // html.document.body!.children.add(anchor); - // anchor.click(); // Programmatically click the link to trigger download - - // html.document.body!.children.remove(anchor); - // html.Url.revokeObjectUrl(url); - // } else { - // var permission = await FlDownloader.requestPermission(); - // if (permission == StoragePermissionStatus.granted) { - // try { - // mihLoadingPopUp(); - // KenLogger.success("Downloading from URL: $url"); - // await FlDownloader.download(url); - // Navigator.of(context).pop(); - // } on Exception catch (error) { - // Navigator.of(context).pop(); - // print(error); - // } - // } else { - // print("denied"); - // } - // try { - // final directory = await getDownloadsDirectory(); - // final file = File('${directory?.path}/$filename'); - // await file.writeAsBytes(imageBytes); - // KenLogger.success("File saved at: ${file.path}"); - // } catch (e) { - // KenLogger.error("Error saving file: $e"); - // } - // } } void mihLoadingPopUp() { @@ -139,10 +102,6 @@ class _MihBusinessQrCodeState extends State { Future downloadQrCode() async { if (_isUserSignedIn) { - // final Uri uri = Uri.parse(getQrCodeData(1024)); - // if (!await launchUrl(uri)) { - // throw 'Could not launch $uri'; - // } await screenshotController.capture().then((image) { KenLogger.success("Image Captured: $image"); setState(() { @@ -244,7 +203,8 @@ class _MihBusinessQrCodeState extends State { if (asyncSnapshot.connectionState == ConnectionState.done && asyncSnapshot.hasData) { - if (asyncSnapshot.requireData != "") { + if (asyncSnapshot.requireData != "" || + asyncSnapshot.requireData.isNotEmpty) { return MihCircleAvatar( imageFile: NetworkImage(asyncSnapshot.requireData), width: profilePictureWidth, @@ -263,7 +223,7 @@ class _MihBusinessQrCodeState extends State { return Icon( MihIcons.iDontKnow, size: profilePictureWidth, - color: MihColors.getSecondaryColor( + color: MihColors.getPrimaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ); @@ -272,7 +232,7 @@ class _MihBusinessQrCodeState extends State { return Icon( MihIcons.mihRing, size: profilePictureWidth, - color: MihColors.getSecondaryColor( + color: MihColors.getPrimaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ); @@ -360,6 +320,13 @@ class _MihBusinessQrCodeState extends State { ); } + void shareMIHLink(BuildContext context, String message, String link) { + String shareText = "$message: $link"; + SharePlus.instance.share( + ShareParams(text: shareText), + ); + } + @override void dispose() { super.dispose(); @@ -431,7 +398,31 @@ class _MihBusinessQrCodeState extends State { onTap: () { downloadQrCode(); }, - ) + ), + SpeedDialChild( + child: Icon( + Icons.share_rounded, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + label: "Share Business", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onTap: () { + shareMIHLink( + context, + "Check out ${widget.business.Name} on the MIH app", + "$qrCodedata${widget.business.business_id}", + ); + }, + ), ]), ) ], diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart index 33330023..42f9f06a 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart @@ -41,6 +41,7 @@ class _MihBusinessReviewsState extends State { businessReview: businessReview, screenWidth: width, readOnly: true, + onSuccessDismissPressed: () {}, ); }, ); diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart index dd129042..c2bc32fb 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart @@ -3,19 +3,17 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; +import 'package:provider/provider.dart'; class MihBusinessUserSearch extends StatefulWidget { - final BusinessArguments arguments; const MihBusinessUserSearch({ super.key, - required this.arguments, }); @override @@ -31,38 +29,24 @@ class _MihBusinessUserSearchState extends State { String errorCode = ""; String errorBody = ""; - Future> fetchUsers(String search) async { - return MihUserServices().searchUsers(search, context); - // final response = await http - // .get(Uri.parse("${AppEnviroment.baseApiUrl}/users/search/$search")); - // errorCode = response.statusCode.toString(); - // errorBody = response.body; - // if (response.statusCode == 200) { - // Iterable l = jsonDecode(response.body); - // List users = - // List.from(l.map((model) => AppUser.fromJson(model))); - // return users; - // } else { - // throw Exception('failed to load patients'); - // } + Future> fetchUsers( + MzansiProfileProvider profileProvider, String search) async { + return MihUserServices().searchUsers(profileProvider, search, context); } - void submitUserForm() { + void submitUserForm(MzansiProfileProvider profileProvider) { if (searchController.text != "") { setState(() { userSearch = searchController.text; hasSearchedBefore = true; - userSearchResults = fetchUsers(userSearch); + userSearchResults = fetchUsers(profileProvider, userSearch); }); } } - Widget displayUserList(List userList) { - if (userList.isNotEmpty) { - return BuildUserList( - users: userList, - arguments: widget.arguments, - ); + Widget displayUserList(MzansiProfileProvider profileProvider) { + if (profileProvider.userSearchResults.isNotEmpty) { + return BuildUserList(); } if (hasSearchedBefore && userSearch.isNotEmpty) { return Column( @@ -161,7 +145,6 @@ class _MihBusinessUserSearchState extends State { @override void initState() { super.initState(); - userSearchResults = fetchUsers("abc"); } @override @@ -183,64 +166,42 @@ class _MihBusinessUserSearchState extends State { } Widget getBody(double width) { - return MihSingleChildScroll( - child: Column(mainAxisSize: MainAxisSize.max, children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: width / 20), - child: MihSearchBar( - controller: searchController, - hintText: "Search Users", - prefixIcon: Icons.search, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - hintColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onPrefixIconTap: () { - submitUserForm(); - }, - onClearIconTap: () { - setState(() { - searchController.clear(); - userSearch = ""; - }); - submitUserForm(); - }, - searchFocusNode: _searchFocusNode, - ), - ), - const SizedBox(height: 10), - FutureBuilder( - future: userSearchResults, - builder: (context, snapshot) { - //print("patient Liust ${snapshot.data}"); - if (snapshot.connectionState == ConnectionState.waiting) { - return const Mihloadingcircle(); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - List patientsList; - if (userSearch == "") { - patientsList = []; - } else { - patientsList = snapshot.data!; - //print(patientsList); - } - return displayUserList(patientsList); - } else { - return Center( - child: Text( - "$errorCode: Error pulling Patients Data\n/users/search/$userSearch\n$errorBody", - style: TextStyle( - fontSize: 25, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark")), - textAlign: TextAlign.center, + // dscvds + return Consumer( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + Widget? child) { + return MihSingleChildScroll( + child: Column( + mainAxisSize: MainAxisSize.max, + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: MihSearchBar( + controller: searchController, + hintText: "Search Users", + prefixIcon: Icons.search, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + hintColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onPrefixIconTap: () { + submitUserForm(profileProvider); + }, + onClearIconTap: () { + setState(() { + searchController.clear(); + userSearch = ""; + }); + }, + searchFocusNode: _searchFocusNode, ), - ); - } - }, - ), - ]), + ), + const SizedBox(height: 10), + displayUserList(profileProvider), + ], + ), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_team.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_team.dart index 651d7d21..3dc774a9 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_team.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_team.dart @@ -1,21 +1,18 @@ -import 'dart:convert'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/builders/build_employee_list.dart'; import 'package:flutter/material.dart'; -import 'package:supertokens_flutter/http.dart' as http; +import 'package:mzansi_innovation_hub/mih_services/mih_business_employee_services.dart'; +import 'package:provider/provider.dart'; class MihMyBusinessTeam extends StatefulWidget { - final BusinessArguments arguments; const MihMyBusinessTeam({ super.key, - required this.arguments, }); @override @@ -23,37 +20,40 @@ class MihMyBusinessTeam extends StatefulWidget { } class _MihMyBusinessTeamState extends State { - late Future> employeeList; - String errorCode = ""; String errorBody = ""; - Future> fetchEmployees() async { - //print("Patien manager page: $endpoint"); - final response = await http.get(Uri.parse( - "${AppEnviroment.baseApiUrl}/business-user/employees/${widget.arguments.businessUser!.business_id}")); - 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) => BusinessEmployee.fromJson(model))); - //print("Here3"); - //print(patientQueue); - return patientQueue; - } else { - throw Exception('failed to load employees'); - } + void getEmployeeData(MzansiProfileProvider mzansiProfileProvider) { + WidgetsBinding.instance.addPostFrameCallback((_) async { + await MihBusinessEmployeeServices() + .fetchEmployees(mzansiProfileProvider, context); + }); } + // Future fetchEmployees( + // MzansiProfileProvider mzansiProfileProvider) async { + // //print("Patien manager page: $endpoint"); + // final response = await http.get(Uri.parse( + // "${AppEnviroment.baseApiUrl}/business-user/employees/${mzansiProfileProvider.businessUser!.business_id}")); + // errorCode = response.statusCode.toString(); + // errorBody = response.body; + // if (response.statusCode == 200) { + // //print("Here1"); + // Iterable l = jsonDecode(response.body); + // //print("Here2"); + // List employeeList = List.from( + // l.map((model) => BusinessEmployee.fromJson(model))); + // mzansiProfileProvider.setEmployeeList(employeeList: employeeList); + // //print("Here3"); + // //print(patientQueue); + // // return patientQueue; + // } else { + // throw Exception('failed to load employees'); + // } + // } Widget displayEmployeeList(List employeeList) { if (employeeList.isNotEmpty) { - return BuildEmployeeList( - employees: employeeList, - arguments: widget.arguments, - ); + return BuildEmployeeList(); } return Center( child: Text( @@ -70,7 +70,10 @@ class _MihMyBusinessTeamState extends State { @override void initState() { super.initState(); - employeeList = fetchEmployees(); + // fetchEmployees(context.read()).catchError((e) { + // // Handle the error thrown in fetchEmployees + // print('Error fetching employees: $e'); + // }); } @override @@ -82,40 +85,21 @@ class _MihMyBusinessTeamState extends State { } Widget getBody() { - return MihSingleChildScroll( - child: Column(mainAxisSize: MainAxisSize.max, children: [ - FutureBuilder( - future: employeeList, - builder: (context, snapshot) { - //print("patient Queue List ${snapshot.hasData}"); - if (snapshot.connectionState == ConnectionState.waiting) { - return const Mihloadingcircle(); - } else if (snapshot.connectionState == ConnectionState.done) { - //List employeeListResults; - // if (searchString == "") { - // patientQueueList = []; - // } else { - - // print(patientQueueList); - // } - - return displayEmployeeList(snapshot.requireData); - } else { - return Center( - child: Text( - "$errorCode: Error pulling Patients Data\n${AppEnviroment.baseApiUrl}/business-user/users/${widget.arguments.businessUser!.business_id}\n$errorBody", - style: TextStyle( - fontSize: 25, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark")), - textAlign: TextAlign.center, - ), - ); - } - }, - ), - ]), + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + if (mzansiProfileProvider.employeeList == null) { + getEmployeeData(mzansiProfileProvider); + return Center( + child: Mihloadingcircle(), + ); + } + return MihSingleChildScroll( + child: Column(mainAxisSize: MainAxisSize.max, children: [ + displayEmployeeList(mzansiProfileProvider.employeeList!), + ]), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_user.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_user.dart index 45e87a65..8bc78d59 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_user.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_user.dart @@ -1,7 +1,9 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; @@ -17,18 +19,11 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:provider/provider.dart'; class MihMyBusinessUser extends StatefulWidget { - final BusinessArguments arguments; - final ImageProvider? userProPicImage; - final ImageProvider? userSignatureImage; - const MihMyBusinessUser({ super.key, - required this.arguments, - required this.userProPicImage, - required this.userSignatureImage, }); @override @@ -37,7 +32,7 @@ class MihMyBusinessUser extends StatefulWidget { class _MihMyBusinessUserState extends State { PlatformFile? userPicFile; - PlatformFile? userSignatureFile; + PlatformFile? newSelectedSignaturePic; final fileNameController = TextEditingController(); final titleTextController = TextEditingController(); final fnameController = TextEditingController(); @@ -55,23 +50,24 @@ class _MihMyBusinessUserState extends State { } } - Future uploadFile() async { - if (userSignatureFile != null) { + Future uploadFile(MzansiProfileProvider mzansiProfileProvider) async { + if (newSelectedSignaturePic != null) { int uploadStatusCode = 0; uploadStatusCode = await MihFileApi.uploadFile( - widget.arguments.signedInUser.app_id, + mzansiProfileProvider.user!.app_id, env, "business_files", - userSignatureFile!, + newSelectedSignaturePic!, context, ); if (uploadStatusCode == 200) { + signtureController.text = newSelectedSignaturePic!.name; int deleteStatusCode = 0; deleteStatusCode = await MihFileApi.deleteFile( - widget.arguments.signedInUser.app_id, + mzansiProfileProvider.user!.app_id, env, "business_files", - widget.arguments.businessUser!.sig_path.split("/").last, + mzansiProfileProvider.businessUser!.sig_path.split("/").last, context, ); if (deleteStatusCode == 200) { @@ -87,42 +83,34 @@ class _MihMyBusinessUserState extends State { } } - Future submitForm() async { + Future submitForm(MzansiProfileProvider mzansiProfileProvider) async { + KenLogger.success("Start Submit Form"); if (isFormFilled()) { - int statusCode = await MihMyBusinessUserServices().updateBusinessUser( - widget.arguments.signedInUser.app_id, - widget.arguments.businessUser!.business_id, - titleTextController.text, - accessController.text, - signtureController.text, - context, - ); - if (statusCode == 200) { - bool successfullyUploadedFile = await uploadFile(); - if (successfullyUploadedFile) { - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pushNamed( - // '/', - // arguments: AuthArguments( - // false, - // false, - // ), - // ); - // File uploaded successfully + KenLogger.success("Form Filled"); + KenLogger.success("Start File Upload"); + bool successfullyUploadedFile = await uploadFile(mzansiProfileProvider); + KenLogger.success( + "File Upload Complete: outcome $successfullyUploadedFile"); + if (!mounted) return; + KenLogger.success("is mounted"); + if (successfullyUploadedFile) { + int statusCode = await MihMyBusinessUserServices().updateBusinessUser( + mzansiProfileProvider.user!.app_id, + mzansiProfileProvider.businessUser!.business_id, + titleTextController.text, + accessController.text, + signtureController.text, + mzansiProfileProvider, + context, + ); + KenLogger.success("Details Update Complete: status code $statusCode"); + if (!mounted) return; + KenLogger.success("is mounted"); + if (statusCode == 200) { + KenLogger.success("Start Success Message"); String message = "Business details updated successfully"; successPopUp(message, false); - // showDialog( - // context: context, - // builder: (context) { - // return const MIHSuccessMessage( - // successType: "Success", - // successMessage: "Business details updated successfully", - // ); - // }, - // ); } else { - // File upload failed showDialog( context: context, builder: (context) { @@ -196,10 +184,7 @@ class _MihMyBusinessUserState extends State { Center( child: MihButton( onPressed: () { - context.goNamed( - 'mihHome', - extra: stayOnPersonalSide, - ); + context.pop(); }, buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -230,6 +215,29 @@ class _MihMyBusinessUserState extends State { ); } + void setControllers() { + MzansiProfileProvider mzansiProfileProvider = + context.read(); + setState(() { + fileNameController.text = + mzansiProfileProvider.user!.pro_pic_path.split("/").last; + signtureController.text = + mzansiProfileProvider.businessUser!.sig_path.split("/").last; + KenLogger.success("title: ${mzansiProfileProvider.businessUser!.title}"); + KenLogger.success( + "sig url: ${mzansiProfileProvider.businessUser!.sig_path}"); + titleTextController.text = mzansiProfileProvider.businessUser!.title; + fnameController.text = mzansiProfileProvider.user!.fname; + lnameController.text = mzansiProfileProvider.user!.lname; + accessController.text = mzansiProfileProvider.businessUser!.access; + }); + if (AppEnviroment.getEnv() == "Prod") { + env = "Prod"; + } else { + env = "Dev"; + } + } + @override void dispose() { super.dispose(); @@ -240,27 +248,13 @@ class _MihMyBusinessUserState extends State { accessController.dispose(); signtureController.dispose(); userPicFile = null; - userSignatureFile = null; + newSelectedSignaturePic = null; } @override void initState() { super.initState(); - setState(() { - fileNameController.text = - widget.arguments.signedInUser.pro_pic_path.split("/").last; - signtureController.text = - widget.arguments.businessUser!.sig_path.split("/").last; - titleTextController.text = widget.arguments.businessUser!.title; - fnameController.text = widget.arguments.signedInUser.fname; - lnameController.text = widget.arguments.signedInUser.lname; - accessController.text = widget.arguments.businessUser!.access; - }); - if (AppEnviroment.getEnv() == "Prod") { - env = "Prod"; - } else { - env = "Dev"; - } + setControllers(); } @override @@ -274,177 +268,200 @@ class _MihMyBusinessUserState extends State { } Widget getBody(double width) { - return MihSingleChildScroll( - child: Padding( - padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.2) - : EdgeInsets.symmetric(horizontal: width * 0.075), - child: Column( - children: [ - MihForm( - formKey: _formKey, - formFields: [ - Center( - child: MihCircleAvatar( - imageFile: widget.userProPicImage, - width: 150, - editable: false, - fileNameController: fileNameController, - userSelectedfile: userPicFile, - frameColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - backgroundColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onChange: (_) {}, - ), - ), - Visibility( - visible: false, - child: MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: fileNameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Selected File Name", - ), - ), - const SizedBox(height: 20), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: titleTextController, - multiLineInput: false, - requiredText: true, - readOnly: false, - hintText: "Title", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: fnameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "First Name", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: lnameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Surname", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: accessController, - multiLineInput: false, - requiredText: true, - hintText: "Access Level", - readOnly: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10), - Container( - width: 300, - alignment: Alignment.topLeft, - child: const Text( - "Signature:", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - ), - Center( - child: MihImageDisplay( - imageFile: widget.userSignatureImage, - width: 300, - height: 200, - editable: true, - fileNameController: signtureController, - userSelectedfile: userSignatureFile, - onChange: (selectedFile) { - setState(() { - userSignatureFile = selectedFile; - }); - }, - ), - ), - const SizedBox(height: 10), - Visibility( - visible: false, - child: MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: fileNameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Selected Signature File", - ), - ), - const SizedBox(height: 15), - Center( - child: MihButton( - onPressed: () { - if (_formKey.currentState!.validate()) { - submitForm(); - } else { - MihAlertServices().formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Text( - "Update", - style: TextStyle( - color: MihColors.getPrimaryColor( + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return MihSingleChildScroll( + child: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: width * 0.2) + : EdgeInsets.symmetric(horizontal: width * 0.075), + child: Column( + children: [ + MihForm( + formKey: _formKey, + formFields: [ + Center( + child: MihCircleAvatar( + imageFile: mzansiProfileProvider.userProfilePicture, + width: 150, + editable: false, + fileNameController: fileNameController, + userSelectedfile: userPicFile, + frameColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: (_) {}, ), ), - ), + Visibility( + visible: false, + child: MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: fileNameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Selected File Name", + ), + ), + const SizedBox(height: 20), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: titleTextController, + multiLineInput: false, + requiredText: true, + readOnly: false, + hintText: "Title", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: fnameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "First Name", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: lnameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Surname", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: accessController, + multiLineInput: false, + requiredText: true, + hintText: "Access Level", + readOnly: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10), + Container( + width: 300, + alignment: Alignment.topLeft, + child: const Text( + "Signature:", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + Center( + child: MihImageDisplay( + imageFile: newSelectedSignaturePic != null + ? MemoryImage(newSelectedSignaturePic!.bytes!) + : mzansiProfileProvider.businessUserSignature, + width: 300, + height: 200, + editable: true, + fileNameController: signtureController, + userSelectedfile: newSelectedSignaturePic, + onChange: (selectedFile) { + setState(() { + newSelectedSignaturePic = selectedFile; + }); + }, + ), + ), + const SizedBox(height: 10), + Visibility( + visible: false, + child: MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: fileNameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Selected Signature File", + ), + ), + const SizedBox(height: 15), + Center( + child: MihButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + submitForm(mzansiProfileProvider); + } else { + MihAlertServices().formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Update", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + const SizedBox(height: 20), + ], ), - const SizedBox(height: 20), ], ), - ], - ), - ), + ), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/components/mih_edit_personal_profile_window.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/components/mih_edit_personal_profile_window.dart new file mode 100644 index 00000000..bd80f937 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/components/mih_edit_personal_profile_window.dart @@ -0,0 +1,579 @@ +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; + +class MihEditPersonalProfileWindow extends StatefulWidget { + const MihEditPersonalProfileWindow({super.key}); + + @override + State createState() => + _MihEditPersonalProfileWindowState(); +} + +class _MihEditPersonalProfileWindowState + extends State { + TextEditingController proPicController = TextEditingController(); + TextEditingController usernameController = TextEditingController(); + TextEditingController fnameController = TextEditingController(); + TextEditingController lnameController = TextEditingController(); + TextEditingController purposeController = TextEditingController(); + bool _controllersInitialized = false; + final ValueNotifier _counter = ValueNotifier(0); + final _formKey = GlobalKey(); + PlatformFile? newSelectedProPic; + String oldProPicName = ""; + String env = ""; + bool businessUser = false; + + void initializeControllers(MzansiProfileProvider mzansiProfileProvider) { + businessUser = mzansiProfileProvider.user!.type == "business"; + oldProPicName = mzansiProfileProvider.user!.pro_pic_path.isNotEmpty + ? mzansiProfileProvider.user!.pro_pic_path.split("/").last + : ""; + env = AppEnviroment.getEnv() == "Prod" ? env = "Prod" : env = "Dev"; + if (!_controllersInitialized && mzansiProfileProvider.user != null) { + usernameController.text = mzansiProfileProvider.user!.username; + fnameController.text = mzansiProfileProvider.user!.fname; + lnameController.text = mzansiProfileProvider.user!.lname; + purposeController.text = mzansiProfileProvider.user!.purpose; + proPicController.text = + mzansiProfileProvider.user!.pro_pic_path.isNotEmpty + ? mzansiProfileProvider.user!.pro_pic_path.split("/").last + : ""; + businessUser = mzansiProfileProvider.user!.type == "business"; + _controllersInitialized = true; + } + } + + Future submitForm(MzansiProfileProvider mzansiProfileProvider) async { + if (mzansiProfileProvider.user!.username != usernameController.text) { + bool isUsernameUnique = await MihUserServices.isUsernameUnique( + usernameController.text, context); + if (isUsernameUnique == false) { + notUniqueAlert(); + return; + } + } + if (oldProPicName != proPicController.text) { + await uploadSelectedFile(mzansiProfileProvider, newSelectedProPic); + } + await updateUserApiCall(mzansiProfileProvider); + } + + Future updateUserApiCall( + MzansiProfileProvider mzansiProfileProvider) async { + KenLogger.success("businessUser: $businessUser"); + int responseCode = await MihUserServices().updateUserV2( + mzansiProfileProvider.user!, + fnameController.text, + lnameController.text, + usernameController.text, + proPicController.text, + purposeController.text, + businessUser, + context, + ); + if (responseCode == 200) { + setState(() { + setProfileVariables(mzansiProfileProvider); + newSelectedProPic = null; + }); + // if (originalProfileTypeIsBusiness == false && businessUser == true) { + // stayOnPersonalSide = false; + // } + String message = "Your information has been updated successfully!"; + successPopUp( + mzansiProfileProvider, + message, + ); + } else { + internetConnectionPopUp(); + } + } + + Future uploadSelectedFile( + MzansiProfileProvider mzansiProfileProvider, PlatformFile? file) async { + var response = await MihFileApi.uploadFile( + mzansiProfileProvider.user!.app_id, + env, + "profile_files", + file, + context, + ); + if (response == 200) { + deleteFileApiCall(mzansiProfileProvider, oldProPicName); + } else { + internetConnectionPopUp(); + } + } + + Future deleteFileApiCall( + MzansiProfileProvider mzansiProfileProvider, String filename) async { + var response = await MihFileApi.deleteFile( + mzansiProfileProvider.user!.app_id, + env, + "profile_files", + filename, + context, + ); + if (response == 200) { + //SQL delete + } else { + internetConnectionPopUp(); + } + } + + void setProfileVariables(MzansiProfileProvider mzansiProfileProvider) { + businessUser = mzansiProfileProvider.user!.type == "business"; + oldProPicName = mzansiProfileProvider.user!.pro_pic_path.isNotEmpty + ? mzansiProfileProvider.user!.pro_pic_path.split("/").last + : ""; + env = AppEnviroment.getEnv() == "Prod" ? env = "Prod" : env = "Dev"; + } + + Color getPurposeLimitColor(int limit) { + if (_counter.value <= limit) { + return MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } else { + return MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } + } + + void successPopUp( + MzansiProfileProvider profileProvider, + String message, + ) { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.check_circle_outline_rounded, + size: 150, + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: "Successfully Updated Profile", + alertBody: Column( + children: [ + Text( + message, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + if (profileProvider.user!.type.toLowerCase() == + "business" && + profileProvider.business == null) { + setupBusinessPopUp(profileProvider); + } else { + context.pop(); + context.pop(); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Dismiss", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + // return MIHSuccessMessage( + // successType: "Success", + // successMessage: message, + // ); + }, + ); + } + + void setupBusinessPopUp( + MzansiProfileProvider profileProvider, + ) { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + MihIcons.businessSetup, + size: 150, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: "Setup Business Profile?", + alertBody: Column( + children: [ + Text( + "It looks like this is the first time activating your business account. Would you like to set up your business now or would you like to do it later?", + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: Wrap( + alignment: WrapAlignment.center, + runAlignment: WrapAlignment.center, + spacing: 10, + runSpacing: 10, + children: [ + MihButton( + onPressed: () { + context.pop(); + context.goNamed( + 'businessProfileSetup', + extra: profileProvider.user, + ); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + elevation: 10, + width: 300, + child: Text( + "Setup Business", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + MihButton( + onPressed: () { + context.pop(); + context.pop(); + context.pop(); + }, + buttonColor: MihColors.getOrangeColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + elevation: 10, + width: 300, + child: Text( + "Setup Later", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ) + ], + ), + alertColour: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + // return MIHSuccessMessage( + // successType: "Success", + // successMessage: message, + // ); + }, + ); + } + + void internetConnectionPopUp() { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Internet Connection"); + }, + ); + } + + void notUniqueAlert() { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.warning_amber_rounded, + size: 100, + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: "Too Slow, That Username is Taken", + alertBody: const Text( + "The username you have entered is already taken by another member of Mzansi. Please choose a different username and try again.", + style: TextStyle( + fontSize: 15, + ), + ), + alertColour: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + ); + } + + @override + void initState() { + super.initState(); + initializeControllers(context.read()); + } + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return MihPackageWindow( + fullscreen: false, + windowTitle: "Edit Profile", + onWindowTapClose: () { + Navigator.of(context).pop(); + }, + windowBody: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: screenWidth * 0.05) + : EdgeInsets.symmetric(horizontal: screenWidth * 0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + MihForm( + formKey: _formKey, + formFields: [ + Center( + child: MihCircleAvatar( + imageFile: newSelectedProPic != null + ? MemoryImage(newSelectedProPic!.bytes!) + : mzansiProfileProvider.userProfilePicture, + width: 150, + editable: true, + fileNameController: proPicController, + userSelectedfile: newSelectedProPic, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: (selectedImage) { + setState(() { + newSelectedProPic = selectedImage; + }); + }, + ), + ), + // const SizedBox(height: 25.0), + Visibility( + visible: false, + child: MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: proPicController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Selected File Name", + ), + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: usernameController, + multiLineInput: false, + requiredText: true, + hintText: "Username", + validator: (value) { + return MihValidationServices().validateUsername(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: fnameController, + multiLineInput: false, + requiredText: true, + hintText: "First Name", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: lnameController, + multiLineInput: false, + requiredText: true, + hintText: "Last Name", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + height: 250, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: purposeController, + multiLineInput: true, + requiredText: true, + hintText: "Your Personal Mission", + validator: (value) { + return MihValidationServices() + .validateLength(purposeController.text, 256); + }, + ), + SizedBox( + height: 15, + child: ValueListenableBuilder( + valueListenable: _counter, + builder: + (BuildContext context, int value, Widget? child) { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "$value", + style: TextStyle( + color: getPurposeLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 5), + Text( + "/256", + style: TextStyle( + color: getPurposeLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + ], + ); + }, + ), + ), + const SizedBox(height: 10.0), + MihToggle( + hintText: "Activate Business Account", + initialPostion: businessUser, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + secondaryFillColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: (value) { + setState(() { + businessUser = value; + }); + KenLogger.success("Business User: $businessUser"); + }, + ), + const SizedBox(height: 30.0), + Center( + child: MihButton( + onPressed: () { + //Add validation here + if (_formKey.currentState!.validate()) { + submitForm(mzansiProfileProvider); + } else { + MihAlertServices().formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + mzansiProfileProvider.user!.username.isEmpty + ? "Setup Profile" + : "Update", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } +} 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 46dea907..a03b4364 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 @@ -2,16 +2,15 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.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'; +import 'package:provider/provider.dart'; class MzansiProfile extends StatefulWidget { - final AppProfileUpdateArguments arguments; const MzansiProfile({ super.key, - required this.arguments, }); @override @@ -19,8 +18,6 @@ class MzansiProfile extends StatefulWidget { } class _MzansiProfileState extends State { - int _selcetedIndex = 0; - @override Widget build(BuildContext context) { return MihPackage( @@ -28,11 +25,9 @@ class _MzansiProfileState extends State { appTools: getTools(), appBody: getToolBody(), appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); + selectedbodyIndex: context.watch().personalIndex, + onIndexChange: (newIndex) { + context.read().setPersonalIndex(newIndex); }, ); } @@ -45,7 +40,6 @@ class _MzansiProfileState extends State { // Navigator.of(context).pop(); context.goNamed( 'mihHome', - extra: true, ); FocusScope.of(context).unfocus(); }, @@ -55,29 +49,25 @@ class _MzansiProfileState extends State { MihPackageTools getTools() { Map temp = {}; temp[const Icon(Icons.person)] = () { - setState(() { - _selcetedIndex = 0; - }); + context.read().setPersonalIndex(0); }; + // temp[const Icon(Icons.person)] = () { + // context.read().setPersonalIndex(1); + // }; temp[const Icon(Icons.settings)] = () { - setState(() { - _selcetedIndex = 1; - }); + context.read().setPersonalIndex(1); }; return MihPackageTools( tools: temp, - selcetedIndex: _selcetedIndex, + selcetedIndex: context.watch().personalIndex, ); } List getToolBody() { List toolBodies = []; - toolBodies.add(MihPersonalProfile( - arguments: widget.arguments, - )); - toolBodies.add(MihPersonalSettings( - signedInUser: widget.arguments.signedInUser, - )); + toolBodies.add(MihPersonalProfile()); + // toolBodies.add(MihPersonalProfile()); + toolBodies.add(MihPersonalSettings()); return toolBodies; } diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart index edea06c9..1eabbf3f 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart @@ -1,6 +1,4 @@ import 'package:go_router/go_router.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; @@ -8,10 +6,8 @@ import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profi import 'package:flutter/material.dart'; class MzansiProfileView extends StatefulWidget { - final AppUser user; const MzansiProfileView({ super.key, - required this.user, }); @override @@ -42,13 +38,7 @@ class _MzansiProfileViewState extends State { icon: const Icon(Icons.arrow_back), iconSize: 35, onTap: () { - context.goNamed( - "mzansiDirectory", - extra: MzansiDirectoryArguments( - personalSearch: true, - startSearchText: widget.user.username, - ), - ); + context.pop(); FocusScope.of(context).unfocus(); }, ); @@ -69,9 +59,9 @@ class _MzansiProfileViewState extends State { List getToolBody() { List toolBodies = []; - toolBodies.add(MihPersonalProfileView( - user: widget.user, - )); + toolBodies.add( + MihPersonalProfileView(), + ); return toolBodies; } diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_profile_tile.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_profile_tile.dart index 730b1f0e..3707b877 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_profile_tile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_profile_tile.dart @@ -2,20 +2,14 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; class MzansiProfileTile extends StatefulWidget { - final AppUser signedInUser; - final ImageProvider? propicFile; final double packageSize; const MzansiProfileTile({ super.key, - required this.signedInUser, - required this.propicFile, required this.packageSize, }); @@ -31,10 +25,6 @@ class _MzansiProfileTileState extends State { onTap: () { context.goNamed( 'mzansiProfileManage', - extra: AppProfileUpdateArguments( - widget.signedInUser, - widget.propicFile, - ), ); }, appName: "Mzansi Profile", diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_setup_profile_tile.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_setup_profile_tile.dart index 37fff79c..abfdf4bf 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_setup_profile_tile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_setup_profile_tile.dart @@ -2,20 +2,14 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; class MzansiSetupProfileTile extends StatefulWidget { - final AppUser signedInUser; - final ImageProvider? propicFile; final double packageSize; const MzansiSetupProfileTile({ super.key, - required this.signedInUser, - required this.propicFile, required this.packageSize, }); @@ -30,10 +24,6 @@ class _MzansiSetupProfileTileState extends State { onTap: () { context.goNamed( 'mzansiProfileManage', - extra: AppProfileUpdateArguments( - widget.signedInUser, - widget.propicFile, - ), ); }, appName: "Set Up Profile", diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart index 97f3900b..c47af691 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart @@ -1,486 +1,48 @@ -import 'package:go_router/go_router.dart'; -import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; +import 'package:ken_logger/ken_logger.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/components/mih_edit_personal_profile_window.dart'; +import 'package:provider/provider.dart'; class MihPersonalProfile extends StatefulWidget { - final AppProfileUpdateArguments arguments; - const MihPersonalProfile({ - super.key, - required this.arguments, - }); + const MihPersonalProfile({super.key}); @override State createState() => _MihPersonalProfileState(); } class _MihPersonalProfileState extends State { - final proPicController = TextEditingController(); - final usernameController = TextEditingController(); - final fnameController = TextEditingController(); - final lnameController = TextEditingController(); - final purposeController = TextEditingController(); - final ValueNotifier _counter = ValueNotifier(0); - PlatformFile? proPic; - late ImageProvider? propicPreview; - late bool originalProfileTypeIsBusiness; - late bool businessUser; - late String oldProPicName; - late String env; - final _formKey = GlobalKey(); - - void notUniqueAlert() { - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.warning_amber_rounded, - size: 100, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: "Too Slow, That Username is Taken", - alertBody: const Text( - "The username you have entered is already taken by another member of Mzansi. Please choose a different username and try again.", - style: TextStyle( - fontSize: 15, - ), - ), - alertColour: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - }, - ); - } - - Future submitForm() async { - // print("============\nsubmiit form\n================="); - if (widget.arguments.signedInUser.username != usernameController.text) { - bool isUsernameUnique = await MihUserServices.isUsernameUnique( - usernameController.text, context); - print("isUsernameUnique: $isUsernameUnique"); - if (isUsernameUnique == false) { - notUniqueAlert(); - return; - } - } - if (oldProPicName != proPicController.text) { - await uploadSelectedFile(proPic); - } - await updateUserApiCall(); - } - - bool isBusinessUser() { - if (widget.arguments.signedInUser.type == "personal") { - return false; - } else { - return true; - } - } - - bool isUsernameValid(String username) { - return RegExp(r'^[a-zA-Z][a-zA-Z0-9_]{5,19}$').hasMatch(username); - } - - Future uploadSelectedFile(PlatformFile? file) async { - var response = await MihFileApi.uploadFile( - widget.arguments.signedInUser.app_id, - env, - "profile_files", - file, - context, - ); - if (response == 200) { - deleteFileApiCall(oldProPicName); - } else { - internetConnectionPopUp(); - } - } - - Future updateUserApiCall() async { - int responseCode = await MihUserServices().updateUserV2( - widget.arguments.signedInUser, - fnameController.text, - lnameController.text, - usernameController.text, - proPicController.text, - purposeController.text, - businessUser, - context, - ); - if (responseCode == 200) { - bool stayOnPersonalSide = true; - if (originalProfileTypeIsBusiness == false && businessUser == true) { - stayOnPersonalSide = false; - } - String message = "Your information has been updated successfully!"; - successPopUp(message, stayOnPersonalSide); - } else { - internetConnectionPopUp(); - } - } - - Future deleteFileApiCall(String filename) async { - var response = await MihFileApi.deleteFile( - widget.arguments.signedInUser.app_id, - env, - "profile_files", - filename, - context, - ); - if (response == 200) { - //SQL delete - } else { - internetConnectionPopUp(); - } - } - - void successPopUp(String message, bool stayOnPersonalSide) { - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.check_circle_outline_rounded, - size: 150, - color: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: "Successfully Updated Profile", - alertBody: Column( - children: [ - Text( - message, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 15, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 25), - Center( - child: MihButton( - onPressed: () { - context.goNamed( - 'mihHome', - extra: stayOnPersonalSide, - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - elevation: 10, - width: 300, - child: Text( - "Dismiss", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ) - ], - ), - alertColour: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - // return MIHSuccessMessage( - // successType: "Success", - // successMessage: message, - // ); - }, - ); - } - - void internetConnectionPopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); - } - - void usernamePopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Invalid Username"); - }, - ); - } - - Color getPurposeLimitColor(int limit) { - if (_counter.value <= limit) { - return MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"); - } else { - return MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"); - } - } + TextEditingController proPicController = TextEditingController(); + PlatformFile? newSelectedProPic; void editProfileWindow(double width) { showDialog( context: context, - builder: (context) => MihPackageWindow( - fullscreen: false, - windowTitle: "Edit Profile", - onWindowTapClose: () { - Navigator.of(context).pop(); + builder: (context) => Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + // usernameController.text = mzansiProfileProvider.user!.username; + // fnameController.text = mzansiProfileProvider.user!.fname; + // lnameController.text = mzansiProfileProvider.user!.lname; + // purposeController.text = mzansiProfileProvider.user!.purpose; + // proPicController.text = + // mzansiProfileProvider.user!.pro_pic_path.isNotEmpty + // ? mzansiProfileProvider.user!.pro_pic_path.split("/").last + // : ""; + return MihEditPersonalProfileWindow(); }, - windowBody: Padding( - padding: - MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.05) - : EdgeInsets.symmetric(horizontal: width * 0), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - MihForm( - formKey: _formKey, - formFields: [ - Center( - child: MihCircleAvatar( - imageFile: propicPreview, - width: 150, - editable: true, - fileNameController: proPicController, - userSelectedfile: proPic, - frameColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - backgroundColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - onChange: (selectedImage) { - setState(() { - proPic = selectedImage; - }); - }, - ), - ), - // const SizedBox(height: 25.0), - Visibility( - visible: false, - child: MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: proPicController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Selected File Name", - ), - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: usernameController, - multiLineInput: false, - requiredText: true, - hintText: "Username", - validator: (value) { - return MihValidationServices().validateUsername(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: fnameController, - multiLineInput: false, - requiredText: true, - hintText: "First Name", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: lnameController, - multiLineInput: false, - requiredText: true, - hintText: "Last Name", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - height: 250, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: purposeController, - multiLineInput: true, - requiredText: true, - hintText: "Your Personal Mission", - validator: (value) { - return MihValidationServices() - .validateLength(purposeController.text, 256); - }, - ), - SizedBox( - height: 15, - child: ValueListenableBuilder( - valueListenable: _counter, - builder: - (BuildContext context, int value, Widget? child) { - return Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - "$value", - style: TextStyle( - color: getPurposeLimitColor(256), - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(width: 5), - Text( - "/256", - style: TextStyle( - color: getPurposeLimitColor(256), - fontWeight: FontWeight.bold, - ), - ), - ], - ); - }, - ), - ), - const SizedBox(height: 10.0), - MihToggle( - hintText: "Activate Business Account", - initialPostion: businessUser, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - secondaryFillColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onChange: (value) { - setState(() { - businessUser = value; - }); - }, - ), - const SizedBox(height: 30.0), - Center( - child: MihButton( - onPressed: () { - //Add validation here - if (_formKey.currentState!.validate()) { - submitForm(); - } else { - MihAlertServices().formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - width: 300, - child: Text( - "Update", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ], - ), - ), ), ); } - @override - void dispose() { - proPicController.dispose(); - usernameController.dispose(); - fnameController.dispose(); - lnameController.dispose(); - purposeController.dispose(); - super.dispose(); - } - - @override - void initState() { - super.initState(); - var proPicName = ""; - if (widget.arguments.signedInUser.pro_pic_path.isNotEmpty) { - proPicName = widget.arguments.signedInUser.pro_pic_path.split("/").last; - } - if (AppEnviroment.getEnv() == "Prod") { - env = "Prod"; - } else { - env = "Dev"; - } - purposeController.addListener(() { - setState(() { - _counter.value = purposeController.text.characters.length; - }); - }); - setState(() { - propicPreview = widget.arguments.propicFile; - oldProPicName = proPicName; - proPicController.text = proPicName; - fnameController.text = widget.arguments.signedInUser.fname; - lnameController.text = widget.arguments.signedInUser.lname; - usernameController.text = widget.arguments.signedInUser.username; - purposeController.text = widget.arguments.signedInUser.purpose; - businessUser = isBusinessUser(); - if (businessUser) { - originalProfileTypeIsBusiness = true; - } else { - originalProfileTypeIsBusiness = false; - } - }); - } - @override Widget build(BuildContext context) { double screenWidth = MediaQuery.of(context).size.width; @@ -492,84 +54,84 @@ class _MihPersonalProfileState extends State { } Widget getBody(double width) { - return Stack( - children: [ - MihSingleChildScroll( - child: Padding( - padding: - MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.2) - : EdgeInsets.symmetric(horizontal: width * 0.075), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Center( - child: MihCircleAvatar( - imageFile: propicPreview, - width: 150, - editable: false, - fileNameController: proPicController, - userSelectedfile: proPic, - frameColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - backgroundColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onChange: (selectedImage) { - setState(() { - proPic = selectedImage; - }); - }, - ), - ), - FittedBox( - child: Text( - widget.arguments.signedInUser.username.isNotEmpty - ? widget.arguments.signedInUser.username - : "username", - style: TextStyle( - fontSize: 35, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + if (mzansiProfileProvider.user == null) { + //Change to new user flow + return Center( + child: Mihloadingcircle(), + ); + } + // else if (mzansiProfileProvider.user!.username.isEmpty) { + // editProfileWindow(width); + // } + else { + KenLogger.success( + mzansiProfileProvider.userProfilePicture.toString()); + return MihSingleChildScroll( + child: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: width * 0.2) + : EdgeInsets.symmetric(horizontal: width * 0.075), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Center( + child: MihCircleAvatar( + imageFile: mzansiProfileProvider.userProfilePicture, + width: 150, + editable: false, + fileNameController: proPicController, + userSelectedfile: newSelectedProPic, + frameColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - ), - FittedBox( - child: Text( - widget.arguments.signedInUser.fname.isNotEmpty - ? "${widget.arguments.signedInUser.fname} ${widget.arguments.signedInUser.lname}" - : "Name Surname", - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( + backgroundColor: MihColors.getPrimaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onChange: (selectedImage) { + setState(() { + newSelectedProPic = selectedImage; + }); + }, + key: ValueKey(mzansiProfileProvider.userProfilePicUrl), ), ), - ), - FittedBox( - child: Text( - businessUser ? "Business" : "Personal", - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - ), - const SizedBox(height: 10.0), - Center( - child: SizedBox( - width: 700, + FittedBox( child: Text( - widget.arguments.signedInUser.purpose.isNotEmpty - ? widget.arguments.signedInUser.purpose - : "No Personal Mission added yet", - textAlign: TextAlign.center, + mzansiProfileProvider.user!.username.isNotEmpty + ? mzansiProfileProvider.user!.username + : "username", + style: TextStyle( + fontSize: 35, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + FittedBox( + child: Text( + mzansiProfileProvider.user!.fname.isNotEmpty + ? "${mzansiProfileProvider.user!.fname} ${mzansiProfileProvider.user!.lname}" + : "Name Surname", + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + FittedBox( + child: Text( + mzansiProfileProvider.user!.type == "business" + ? "Business".toUpperCase() + : "Personal".toUpperCase(), style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, @@ -579,63 +141,56 @@ class _MihPersonalProfileState extends State { ), ), ), - ), - const SizedBox(height: 30.0), - Center( - child: MihButton( - onPressed: () { - // Connect with the user - editProfileWindow(width); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Text( - widget.arguments.signedInUser.username.isEmpty - ? "Set Up Profile" - : "Edit Profile", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, + const SizedBox(height: 10.0), + Center( + child: SizedBox( + width: 700, + child: Text( + mzansiProfileProvider.user!.purpose.isNotEmpty + ? mzansiProfileProvider.user!.purpose + : "No Personal Mission added yet", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), ), ), ), - ), - ], + const SizedBox(height: 30.0), + Center( + child: MihButton( + onPressed: () { + // Connect with the user + editProfileWindow(width); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + mzansiProfileProvider.user!.username.isEmpty + ? "Set Up Profile" + : "Edit Profile", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), ), - ), - ), - // Positioned( - // right: 5, - // bottom: 10, - // child: MihFloatingMenu( - // animatedIcon: AnimatedIcons.menu_close, - // children: [ - // SpeedDialChild( - // child: Icon( - // Icons.edit, - // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // label: "Edit Profile", - // labelBackgroundColor: - // MihColors.getGreenColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // labelStyle: TextStyle( - // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // fontWeight: FontWeight.bold, - // ), - // backgroundColor: - // MihColors.getGreenColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // onTap: () { - // editProfileWindow(width); - // }, - // ) - // ], - // ), - // ), - ], + ); + } + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile_view.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile_view.dart index 7ec7447d..58a005c1 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile_view.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile_view.dart @@ -1,6 +1,6 @@ import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; @@ -8,12 +8,11 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MihPersonalProfileView extends StatefulWidget { - final AppUser user; const MihPersonalProfileView({ super.key, - required this.user, }); @override @@ -32,8 +31,10 @@ class _MihPersonalProfileViewState extends State { @override void initState() { super.initState(); - futureImageUrl = - MihFileApi.getMinioFileUrl(widget.user.pro_pic_path, context); + MzansiDirectoryProvider directoryProvider = + context.read(); + futureImageUrl = MihFileApi.getMinioFileUrl( + directoryProvider.selectedUser!.pro_pic_path, context); } @override @@ -48,152 +49,123 @@ class _MihPersonalProfileViewState extends State { Widget getBody(double width) { double profilePictureWidth = 150; - return MihSingleChildScroll( - child: Padding( - padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.2) - : EdgeInsets.symmetric(horizontal: width * 0.075), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - FutureBuilder( - future: futureImageUrl, - builder: (context, asyncSnapshot) { - if (asyncSnapshot.connectionState == ConnectionState.done && - asyncSnapshot.hasData) { - if (asyncSnapshot.requireData != "") { - return MihCircleAvatar( - imageFile: NetworkImage(asyncSnapshot.requireData), - width: profilePictureWidth, - editable: false, - fileNameController: TextEditingController(), - userSelectedfile: file, - frameColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - backgroundColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - onChange: () {}, - ); - } else { - return Icon( - MihIcons.iDontKnow, - size: profilePictureWidth, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ); - } - } else { - return Icon( - MihIcons.mihRing, - size: profilePictureWidth, + return Consumer( + builder: (BuildContext context, MzansiDirectoryProvider directoryProvider, + Widget? child) { + return MihSingleChildScroll( + child: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: width * 0.2) + : EdgeInsets.symmetric(horizontal: width * 0.075), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + FutureBuilder( + future: futureImageUrl, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == + ConnectionState.done && + asyncSnapshot.hasData) { + if (asyncSnapshot.requireData != "") { + return MihCircleAvatar( + imageFile: NetworkImage(asyncSnapshot.requireData), + width: profilePictureWidth, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.iDontKnow, + size: profilePictureWidth, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ); + } + } else { + return Icon( + MihIcons.mihRing, + size: profilePictureWidth, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ); + } + }), + FittedBox( + child: Text( + directoryProvider.selectedUser!.username.isNotEmpty + ? directoryProvider.selectedUser!.username + : "Username", + style: TextStyle( + fontSize: 35, + fontWeight: FontWeight.bold, color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - } - // return Center( - // child: MihCircleAvatar( - // imageFile: propicPreview, - // width: 150, - // editable: false, - // fileNameController: proPicController, - // userSelectedfile: proPic, - // frameColor: MzansiInnovationHub.of(context)! - // .theme - // .secondaryColor(), - // backgroundColor: - // MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // onChange: (selectedImage) { - // setState(() { - // proPic = selectedImage; - // }); - // }, - // ), - // ); - }), - FittedBox( - child: Text( - widget.user.username.isNotEmpty - ? widget.user.username - : "Username", - style: TextStyle( - fontSize: 35, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - ), - FittedBox( - child: Text( - widget.user.fname.isNotEmpty - ? "${widget.user.fname} ${widget.user.lname}" - : "Name Surname", - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - ), - FittedBox( - child: Text( - widget.user.type.toUpperCase(), - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - ), - const SizedBox(height: 10.0), - Center( - child: SizedBox( - width: 700, - child: Text( - widget.user.purpose.isNotEmpty - ? widget.user.purpose - : "No Personal Mission added yet", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), ), ), - ), + FittedBox( + child: Text( + directoryProvider.selectedUser!.fname.isNotEmpty + ? "${directoryProvider.selectedUser!.fname} ${directoryProvider.selectedUser!.lname}" + : "Name Surname", + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + FittedBox( + child: Text( + directoryProvider.selectedUser!.type.toUpperCase(), + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + const SizedBox(height: 10.0), + Center( + child: SizedBox( + width: 700, + child: Text( + directoryProvider.selectedUser!.purpose.isNotEmpty + ? directoryProvider.selectedUser!.purpose + : "No Personal Mission added yet", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + ), + const SizedBox(height: 30.0), + ], ), - const SizedBox(height: 30.0), - // Center( - // child: MihButton( - // onPressed: () { - // // Connect with the user - // }, - // buttonColor: - // MihColors.getGreenColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // width: 300, - // child: Text( - // widget.user.username.isEmpty - // ? "Set Up Profile" - // : "Edit Profile", - // style: TextStyle( - // color: - // MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // fontSize: 20, - // fontWeight: FontWeight.bold, - // ), - // ), - // ), - // ), - ], - ), - ), + ), + ); + }, ); } } 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 index 7a7eeac9..1427074d 100644 --- 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 @@ -1,19 +1,18 @@ import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:provider/provider.dart'; class MihPersonalSettings extends StatefulWidget { - final AppUser signedInUser; const MihPersonalSettings({ super.key, - required this.signedInUser, }); @override @@ -35,75 +34,83 @@ class _MihPersonalSettingsState extends State { context: context, barrierDismissible: false, builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.warning_amber_rounded, - size: 100, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - 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: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 15, - fontWeight: FontWeight.bold, - ), + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return MihPackageAlert( + alertIcon: Icon( + Icons.warning_amber_rounded, + size: 100, + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), - const SizedBox(height: 15), - Wrap( - spacing: 10, - runSpacing: 10, + alertTitle: + "Are you sure you want to permanently delete your MIH account?", + alertBody: Column( + mainAxisSize: MainAxisSize.min, children: [ - MihButton( - onPressed: () { - MihUserServices.deleteAccount( - widget.signedInUser.app_id, context); - }, - buttonColor: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Text( - "Delete", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), + 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: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, ), ), - MihButton( - onPressed: () { - Navigator.pop(context); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Text( - "Cancel", - style: TextStyle( - color: MihColors.getPrimaryColor( + const SizedBox(height: 15), + Wrap( + spacing: 10, + runSpacing: 10, + children: [ + MihButton( + onPressed: () { + MihUserServices.deleteAccount( + mzansiProfileProvider, context); + }, + buttonColor: MihColors.getRedColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, + width: 300, + child: Text( + "Delete", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), ), - ), - ), + MihButton( + onPressed: () { + Navigator.pop(context); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Cancel", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ) ], - ) - ], - ), - alertColour: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertColour: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, ); }, ); 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 index b791c364..f44e7afb 100644 --- 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 @@ -3,10 +3,12 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:go_router/go_router.dart'; import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_banner_ad.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_wallet_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_wallet_services.dart'; @@ -17,31 +19,25 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/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:barcode_widget/barcode_widget.dart'; +import 'package:provider/provider.dart'; import 'package:screen_brightness/screen_brightness.dart'; class BuildLoyaltyCardList extends StatefulWidget { - final AppUser signedInUser; final List cardList; final int navIndex; - final MihBannerAd? bannerAd; final bool favouritesMode; final TextEditingController searchText; - final void Function()? onCardViewClose; const BuildLoyaltyCardList({ super.key, - required this.signedInUser, required this.cardList, required this.navIndex, required this.favouritesMode, required this.searchText, - this.bannerAd, - this.onCardViewClose, }); @override @@ -62,7 +58,8 @@ class _BuildLoyaltyCardListState extends State { ); } - void editCardWindow(BuildContext ctxt, int index, double width) { + void editCardWindow(MzansiProfileProvider mzansiProfileProvider, + BuildContext ctxt, int index, double width) { showDialog( context: context, barrierDismissible: false, @@ -147,8 +144,9 @@ class _BuildLoyaltyCardListState extends State { if (_formKey.currentState!.validate()) { int statusCode = await MIHMzansiWalletApis .updateLoyaltyCardAPICall( - widget.signedInUser, + mzansiProfileProvider.user!, widget.cardList[index].idloyalty_cards, + widget.cardList[index].shop_name, widget.cardList[index].favourite, widget.cardList[index].priority_index, _nicknameController.text, @@ -158,13 +156,28 @@ class _BuildLoyaltyCardListState extends State { if (statusCode == 200) { context.pop(); context.pop(); - context.goNamed( - "mzansiWallet", - extra: WalletArguments( - widget.signedInUser, - 0, - ), - ); + // context + // .read() + // .editLoyaltyCard( + // updatedCard: MIHLoyaltyCard( + // idloyalty_cards: + // widget.cardList[index].idloyalty_cards, + // app_id: widget.signedInUser.app_id, + // shop_name: widget.cardList[index].shop_name, + // card_number: _cardNumberController.text, + // favourite: widget.cardList[index].favourite, + // priority_index: + // widget.cardList[index].priority_index, + // nickname: _nicknameController.text, + // ), + // ); + // context.goNamed( + // "mzansiWallet", + // extra: WalletArguments( + // widget.signedInUser, + // 0, + // ), + // ); } else { internetConnectionPopUp(); } @@ -197,7 +210,8 @@ class _BuildLoyaltyCardListState extends State { ); } - void deleteCardWindow(BuildContext ctxt, int index) { + void deleteCardWindow(MzansiProfileProvider mzansiProfileProvider, + BuildContext ctxt, int index) { showDialog( context: context, barrierDismissible: false, @@ -207,14 +221,11 @@ class _BuildLoyaltyCardListState extends State { onTap: () async { int statusCode = await MIHMzansiWalletApis.deleteLoyaltyCardAPICall( - widget.signedInUser, + mzansiProfileProvider.user!, widget.cardList[index].idloyalty_cards, context, ); if (statusCode == 200) { - setState(() { - widget.cardList.removeAt(index); - }); context.pop(); context.pop(); } else { @@ -226,7 +237,8 @@ class _BuildLoyaltyCardListState extends State { ); } - void addToFavCardWindow(BuildContext ctxt, int index) { + void addToFavCardWindow(MzansiProfileProvider mzansiProfileProvider, + BuildContext ctxt, int index) { showDialog( context: context, barrierDismissible: false, @@ -258,8 +270,9 @@ class _BuildLoyaltyCardListState extends State { onPressed: () async { int statusCode = await MIHMzansiWalletApis.updateLoyaltyCardAPICall( - widget.signedInUser, + mzansiProfileProvider.user!, widget.cardList[index].idloyalty_cards, + widget.cardList[index].shop_name, "Yes", _noFavourites, widget.cardList[index].nickname, @@ -269,13 +282,11 @@ class _BuildLoyaltyCardListState extends State { if (statusCode == 200) { context.pop(); context.pop(); - context.goNamed( - "mzansiWallet", - extra: WalletArguments( - widget.signedInUser, - 1, - ), + await MIHMzansiWalletApis.getFavouriteLoyaltyCards( + mzansiProfileProvider.user!.app_id, + context, ); + context.read().setToolIndex(1); } else { internetConnectionPopUp(); } @@ -311,7 +322,8 @@ class _BuildLoyaltyCardListState extends State { ); } - void removeFromFavCardWindow(BuildContext ctxt, int index) { + void removeFromFavCardWindow(MzansiProfileProvider mzansiProfileProvider, + BuildContext ctxt, int index) { showDialog( context: context, barrierDismissible: false, @@ -343,8 +355,9 @@ class _BuildLoyaltyCardListState extends State { onPressed: () async { int statusCode = await MIHMzansiWalletApis.updateLoyaltyCardAPICall( - widget.signedInUser, + mzansiProfileProvider.user!, widget.cardList[index].idloyalty_cards, + widget.cardList[index].shop_name, "", 0, widget.cardList[index].nickname, @@ -354,13 +367,11 @@ class _BuildLoyaltyCardListState extends State { if (statusCode == 200) { context.pop(); context.pop(); - context.goNamed( - "mzansiWallet", - extra: WalletArguments( - widget.signedInUser, - 0, - ), + await MIHMzansiWalletApis.getFavouriteLoyaltyCards( + mzansiProfileProvider.user!.app_id, + context, ); + context.read().setToolIndex(0); } else { internetConnectionPopUp(); } @@ -385,7 +396,8 @@ class _BuildLoyaltyCardListState extends State { ); } - void viewCardWindow(int index, double width) { + void viewCardWindow( + MzansiProfileProvider mzansiProfileProvider, int index, double width) { //print(widget.cardList[index].card_number); String formattedCardNumber = ""; for (int i = 0; i <= widget.cardList[index].card_number.length - 1; i++) { @@ -427,9 +439,17 @@ class _BuildLoyaltyCardListState extends State { MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { if (widget.cardList[index].favourite == "") { - addToFavCardWindow(context, index); + addToFavCardWindow( + mzansiProfileProvider, + context, + index, + ); } else { - removeFromFavCardWindow(context, index); + removeFromFavCardWindow( + mzansiProfileProvider, + context, + index, + ); } }, ), @@ -454,7 +474,12 @@ class _BuildLoyaltyCardListState extends State { _cardNumberController.text = widget.cardList[index].card_number; _nicknameController.text = widget.cardList[index].nickname; }); - editCardWindow(context, index, width); + editCardWindow( + mzansiProfileProvider, + context, + index, + width, + ); }, ), SpeedDialChild( @@ -474,12 +499,16 @@ class _BuildLoyaltyCardListState extends State { backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - deleteCardWindow(context, index); + deleteCardWindow( + mzansiProfileProvider, + context, + index, + ); }, ), ], onWindowTapClose: () { - widget.onCardViewClose; + context.read().loadBannerAd(); resetScreenBrightness(); context.pop(); }, @@ -541,7 +570,9 @@ class _BuildLoyaltyCardListState extends State { ), ), SizedBox(height: 10), - widget.bannerAd ?? SizedBox(), + Consumer(builder: (context, bannerAdDisplay, child) { + return MihBannerAd(); + }), // MihBannerAd(), ], ), @@ -674,29 +705,38 @@ class _BuildLoyaltyCardListState extends State { // final double width = size.width; //final double height = size.height; if (widget.cardList.isNotEmpty) { - return GridView.builder( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - padding: EdgeInsets.only( - left: getHorizontalPaddingSize(size), - right: getHorizontalPaddingSize(size), - ), - itemCount: widget.cardList.length, - gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( - mainAxisSpacing: 0, - crossAxisSpacing: 5, - maxCrossAxisExtent: 200, - ), - itemBuilder: (context, index) { - return GestureDetector( - child: MihCardDisplay( - shopName: widget.cardList[index].shop_name, - nickname: widget.cardList[index].nickname, - height: 100, + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return GridView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: EdgeInsets.only( + left: getHorizontalPaddingSize(size), + right: getHorizontalPaddingSize(size), ), - onTap: () { - setScreenBrightness(1.0); - viewCardWindow(index, size.width); + itemCount: widget.cardList.length, + gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( + mainAxisSpacing: 0, + crossAxisSpacing: 5, + maxCrossAxisExtent: 200, + ), + itemBuilder: (context, index) { + return GestureDetector( + child: MihCardDisplay( + shopName: widget.cardList[index].shop_name, + nickname: widget.cardList[index].nickname, + height: 100, + ), + onTap: () { + setScreenBrightness(1.0); + viewCardWindow( + mzansiProfileProvider, + index, + size.width, + ); + }, + ); }, ); }, diff --git a/Frontend/lib/mih_packages/mzansi_wallet/components/mih_add_card_window.dart b/Frontend/lib/mih_packages/mzansi_wallet/components/mih_add_card_window.dart index b194d0ce..b1e69c35 100644 --- a/Frontend/lib/mih_packages/mzansi_wallet/components/mih_add_card_window.dart +++ b/Frontend/lib/mih_packages/mzansi_wallet/components/mih_add_card_window.dart @@ -1,12 +1,7 @@ -// ignore_for_file: must_be_immutable - import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/loyalty_card.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; @@ -14,20 +9,17 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/components/mih_card_display.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_wallet_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; class MihAddCardWindow extends StatefulWidget { - final AppUser signedInUser; - Future> cardList; - - MihAddCardWindow({ + const MihAddCardWindow({ super.key, - required this.signedInUser, - required this.cardList, }); @override @@ -82,7 +74,6 @@ class _MihAddCardWindowState extends State { context.pop(); context.goNamed( 'mzansiWallet', - extra: WalletArguments(widget.signedInUser, 0), ); }, buttonColor: MihColors.getGreenColor( @@ -133,8 +124,6 @@ class _MihAddCardWindowState extends State { } } - // ... rest of your existing methods - @override Widget build(BuildContext context) { final double width = MediaQuery.sizeOf(context).width; @@ -152,211 +141,217 @@ class _MihAddCardWindowState extends State { padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop" ? EdgeInsets.symmetric(horizontal: width * 0.05) : EdgeInsets.symmetric(horizontal: width * 0), - child: Column( - children: [ - MihForm( - formKey: _formKey, - formFields: [ - MihDropdownField( - controller: _shopController, - hintText: "Shop Name", - editable: true, - enableSearch: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - requiredText: true, - dropdownOptions: const [ - "+More", - "Apple Tree", - "+More", - "Apple Tree", - "Auchan", - "Best Before", - "Big Save", - "Boxer", - "BP", - "Builders Warehouse", - "Checkers", - "Choppies", - "Clicks", - "Continente", - "Cotton:On", - "Carrefour", - "Dis-Chem", - "Edgars", - "Eskom", - "Exclusive Books", - "Fresh Stop", - "Fresmart", - "Infinity", - "Jet", - "Justrite", - "Kero", - "Leroy Merlin", - "Makro", - "Naivas", - "OK Foods", - "Panarottis", - "Pick n Pay", - "PnA", - "PQ Clothing", - "Rage", - "Sefalana", - "Sasol", - "Shell", - "Shoprite", - "Signature Cosmetics & Fragrances", - "Spar", - "Spur", - "TFG Group", - "Total Energies", - "Toys R Us", - "Woermann Brock", - "Woolworths" - ], - ), - 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, - nickname: "", - height: 200), - ], - ), - ); - }, - ), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: _nicknameController, - multiLineInput: false, - requiredText: false, - hintText: "Card Title", - ), - const SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - mainAxisSize: MainAxisSize.max, - children: [ - Flexible( - child: MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: _cardNumberController, - multiLineInput: false, - requiredText: true, - hintText: "Card Number", - numberMode: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), + child: Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return Column( + children: [ + MihForm( + formKey: _formKey, + formFields: [ + MihDropdownField( + controller: _shopController, + hintText: "Shop Name", + editable: true, + enableSearch: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + requiredText: true, + dropdownOptions: const [ + "+More", + "Apple Tree", + "+More", + "Apple Tree", + "Auchan", + "Best Before", + "Big Save", + "Boxer", + "BP", + "Builders Warehouse", + "Checkers", + "Choppies", + "Clicks", + "Continente", + "Cotton:On", + "Carrefour", + "Dis-Chem", + "Edgars", + "Engen", + "Eskom", + "Exclusive Books", + "Fresh Stop", + "Fresmart", + "Infinity", + "Jet", + "Justrite", + "Kero", + "Leroy Merlin", + "Makro", + "Naivas", + "OK Foods", + "Panarottis", + "Pick n Pay", + "PnA", + "PQ Clothing", + "Rage", + "Sefalana", + "Sasol", + "Shell", + "Shoprite", + "Signature Cosmetics & Fragrances", + "Spar", + "Spur", + "TFG Group", + "Total Energies", + "Toys R Us", + "Woermann Brock", + "Woolworths" + ], ), - const SizedBox(width: 20), - MihButton( - onPressed: () { - context.pushNamed( - "barcodeScanner", - extra: _cardNumberController, // Use local controller + 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, + nickname: "", + height: 200), + ], + ), ); }, - buttonColor: MihColors.getSecondaryColor( + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 100, - child: Text( - "Scan", - style: TextStyle( - color: MihColors.getPrimaryColor( + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: _nicknameController, + multiLineInput: false, + requiredText: false, + hintText: "Card Title", + ), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + child: MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: _cardNumberController, + multiLineInput: false, + requiredText: true, + hintText: "Card Number", + numberMode: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + ), + const SizedBox(width: 20), + MihButton( + onPressed: () { + context.pushNamed( + "barcodeScanner", + extra: + _cardNumberController, // Use local controller + ); + }, + buttonColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, + width: 100, + child: Text( + "Scan", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + const SizedBox(height: 15), + Center( + child: MihButton( + onPressed: () async { + if (_formKey.currentState!.validate()) { + if (_shopController.text == "") { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage( + errorType: "Input Error"); + }, + ); + } else { + int statusCode = await MIHMzansiWalletApis + .addLoyaltyCardAPICall( + mzansiProfileProvider.user!, + mzansiProfileProvider.user!.app_id, + _shopController.text, + _cardNumberController.text, + "", + 0, + _nicknameController.text, + context, + ); + if (statusCode == 201) { + context.pop(); + KenLogger.error("Card Added Successfully"); + successPopUp( + "Successfully Added Card", + "The loyalty card has been added to your favourites.", + 0, + ); + } else { + internetConnectionPopUp(); + } + } + } else { + MihAlertServices().formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Add", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), ), ), ), ], ), - const SizedBox(height: 15), - Center( - child: MihButton( - onPressed: () async { - if (_formKey.currentState!.validate()) { - if (_shopController.text == "") { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage( - errorType: "Input Error"); - }, - ); - } else { - int statusCode = - await MIHMzansiWalletApis.addLoyaltyCardAPICall( - widget.signedInUser, - widget.signedInUser.app_id, - _shopController.text, - _cardNumberController.text, - "", - 0, - _nicknameController.text, - context, - ); - if (statusCode == 201) { - setState(() { - widget.cardList = - MIHMzansiWalletApis.getLoyaltyCards( - widget.signedInUser.app_id); - }); - context.pop(); - KenLogger.error("Card Added Successfully"); - successPopUp( - "Successfully Added Card", - "The loyalty card has been added to your favourites.", - 0, - ); - } else { - internetConnectionPopUp(); - } - } - } else { - MihAlertServices().formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Text( - "Add", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), ], - ), - ], + ); + }, ), ), ); 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 index 5f590c57..4829c409 100644 --- a/Frontend/lib/mih_packages/mzansi_wallet/components/mih_card_display.dart +++ b/Frontend/lib/mih_packages/mzansi_wallet/components/mih_card_display.dart @@ -153,6 +153,9 @@ class _MihCardDisplayState extends State { case "total energies": return Image.asset( 'lib/mih_components/mih_package_components/assets/images/loyalty_cards/mini/total_energies-min.png'); + case "engen": + return Image.asset( + 'lib/mih_components/mih_package_components/assets/images/loyalty_cards/mini/engen-min.png'); default: return null; } diff --git a/Frontend/lib/mih_packages/mzansi_wallet/mih_wallet.dart b/Frontend/lib/mih_packages/mzansi_wallet/mih_wallet.dart index bff4aa00..bfc58d34 100644 --- a/Frontend/lib/mih_packages/mzansi_wallet/mih_wallet.dart +++ b/Frontend/lib/mih_packages/mzansi_wallet/mih_wallet.dart @@ -2,18 +2,19 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_wallet_provider.dart'; +import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/package_tools/mih_card_favourites.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/package_tools/mih_cards.dart'; -import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_wallet_services.dart'; +import 'package:provider/provider.dart'; class MihWallet extends StatefulWidget { - final WalletArguments arguments; - // final AppUser signedInUser; const MihWallet({ super.key, - required this.arguments, - // required this.signedInUser, }); @override @@ -21,13 +22,31 @@ class MihWallet extends StatefulWidget { } class _MihWalletState extends State { - late int _selcetedIndex; + bool isLoading = true; + + Future setLoyaltyCards( + MzansiProfileProvider mzansiProfileProvider) async { + await MIHMzansiWalletApis.getLoyaltyCards( + mzansiProfileProvider.user!.app_id, context); + } + + Future setFavouritesCards( + MzansiProfileProvider mzansiProfileProvider) async { + await MIHMzansiWalletApis.getFavouriteLoyaltyCards( + mzansiProfileProvider.user!.app_id, context); + } @override void initState() { super.initState(); - setState(() { - _selcetedIndex = widget.arguments.index; + WidgetsBinding.instance.addPostFrameCallback((_) async { + var mzansiProfileProvider = context.read(); + await setLoyaltyCards(mzansiProfileProvider); + await setFavouritesCards(mzansiProfileProvider); + context.read().loadBannerAd(); + setState(() { + isLoading = false; + }); }); } @@ -38,12 +57,13 @@ class _MihWalletState extends State { appTools: getTools(), appBody: getToolBody(), appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); - print("Index: $_selcetedIndex"); + selectedbodyIndex: context.watch().toolIndex, + onIndexChange: (newIndex) { + context.read().setToolIndex(newIndex); + // setState(() { + // _selcetedIndex = newValue; + // }); + // print("Index: $_selcetedIndex"); }, ); } @@ -55,7 +75,6 @@ class _MihWalletState extends State { onTap: () { context.goNamed( 'mihHome', - extra: true, ); FocusScope.of(context).unfocus(); }, @@ -65,31 +84,30 @@ class _MihWalletState extends State { MihPackageTools getTools() { Map temp = {}; temp[const Icon(Icons.card_membership)] = () { - setState(() { - _selcetedIndex = 0; - }); + context.read().setToolIndex(0); }; temp[const Icon(Icons.favorite)] = () { - setState(() { - _selcetedIndex = 1; - }); + context.read().setToolIndex(1); }; return MihPackageTools( tools: temp, - selcetedIndex: _selcetedIndex, + selcetedIndex: context.watch().toolIndex, ); } List getToolBody() { List toolBodies = [ - MihCards( - signedInUser: widget.arguments.signedInUser, - ), - MihCardFavourites( - signedInUser: widget.arguments.signedInUser, - ), + MihCards(), + MihCardFavourites(), ]; + if (isLoading) { + return [ + const Center( + child: Mihloadingcircle(), + ) + ]; + } return toolBodies; } diff --git a/Frontend/lib/mih_packages/mzansi_wallet/package_tiles/mih_wallet_tile.dart b/Frontend/lib/mih_packages/mzansi_wallet/package_tiles/mih_wallet_tile.dart index ddb89401..baa72c54 100644 --- a/Frontend/lib/mih_packages/mzansi_wallet/package_tiles/mih_wallet_tile.dart +++ b/Frontend/lib/mih_packages/mzansi_wallet/package_tiles/mih_wallet_tile.dart @@ -2,18 +2,14 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:flutter/material.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; class MihWalletTile extends StatefulWidget { - final AppUser signedInUser; final double packageSize; const MihWalletTile({ super.key, - required this.signedInUser, required this.packageSize, }); @@ -29,7 +25,6 @@ class _MihWalletTileState extends State { onTap: () { context.goNamed( 'mzansiWallet', - extra: WalletArguments(widget.signedInUser, 0), ); // Navigator.of(context).pushNamed( // '/mzansi-wallet', diff --git a/Frontend/lib/mih_packages/mzansi_wallet/package_tools/mih_card_favourites.dart b/Frontend/lib/mih_packages/mzansi_wallet/package_tools/mih_card_favourites.dart index 2cd705e2..5df6695c 100644 --- a/Frontend/lib/mih_packages/mzansi_wallet/package_tools/mih_card_favourites.dart +++ b/Frontend/lib/mih_packages/mzansi_wallet/package_tools/mih_card_favourites.dart @@ -1,18 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_banner_ad.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_wallet_services.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_wallet_provider.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/loyalty_card.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/builder/build_loyalty_card_list.dart'; +import 'package:provider/provider.dart'; class MihCardFavourites extends StatefulWidget { - final AppUser signedInUser; const MihCardFavourites({ super.key, - required this.signedInUser, }); @override @@ -21,16 +17,18 @@ class MihCardFavourites extends StatefulWidget { class _MihCardFavouritesState extends State { late Future> cardList; - late MihBannerAd _bannerAd; List listOfCards = []; + void getFavouriteLoyaltyCards(BuildContext context) async { + setState(() { + listOfCards = context.read().favouriteCards; + }); + } + @override void initState() { + getFavouriteLoyaltyCards(context); super.initState(); - _bannerAd = MihBannerAd(); - cardList = MIHMzansiWalletApis.getFavouriteLoyaltyCards( - widget.signedInUser.app_id, - ); } @override @@ -47,69 +45,15 @@ class _MihCardFavouritesState extends State { MihSingleChildScroll( child: Column( children: [ - FutureBuilder( - future: cardList, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center( - child: Mihloadingcircle(), - ); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - listOfCards = snapshot.data!; - // searchShop(); - return BuildLoyaltyCardList( - cardList: listOfCards, - signedInUser: widget.signedInUser, - navIndex: 0, - bannerAd: _bannerAd, - favouritesMode: true, - searchText: TextEditingController(), - onCardViewClose: () { - setState(() { - _bannerAd = MihBannerAd(); - }); - Navigator.pop(context); - }, - ); - } else { - return const Center( - child: Text("Error Loading Loyalty Cards"), - ); - } - }, + BuildLoyaltyCardList( + cardList: listOfCards, + navIndex: 0, + favouritesMode: true, + searchText: TextEditingController(), ), ], ), ), - // Positioned( - // right: 0, - // bottom: 0, - // child: MihFloatingMenu( - // animatedIcon: AnimatedIcons.menu_close, - // children: [ - // SpeedDialChild( - // child: Icon( - // Icons.add, - // color: - // MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // label: "Add Loyalty Card", - // labelBackgroundColor: - // MihColors.getGreenColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // labelStyle: TextStyle( - // color: - // MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // fontWeight: FontWeight.bold, - // ), - // backgroundColor: - // MihColors.getGreenColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // onTap: () { - // // addCardWindow(context); - // }, - // ) - // ]), - // ) ], ); } diff --git a/Frontend/lib/mih_packages/mzansi_wallet/package_tools/mih_cards.dart b/Frontend/lib/mih_packages/mzansi_wallet/package_tools/mih_cards.dart index e806717c..089a382d 100644 --- a/Frontend/lib/mih_packages/mzansi_wallet/package_tools/mih_cards.dart +++ b/Frontend/lib/mih_packages/mzansi_wallet/package_tools/mih_cards.dart @@ -1,29 +1,25 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_banner_ad.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_wallet_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/components/mih_add_card_window.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_wallet_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; 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_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/loyalty_card.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/builder/build_loyalty_card_list.dart'; import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:provider/provider.dart'; class MihCards extends StatefulWidget { - final AppUser signedInUser; const MihCards({ super.key, - required this.signedInUser, }); @override @@ -33,8 +29,6 @@ class MihCards extends StatefulWidget { class _MihCardsState extends State { final TextEditingController cardSearchController = TextEditingController(); final FocusNode searchFocusNode = FocusNode(); - late Future> cardList; - MihBannerAd _bannerAd = MihBannerAd(); List listOfCards = []; final ValueNotifier> searchShopName = ValueNotifier([]); final MobileScannerController scannerController = MobileScannerController( @@ -130,10 +124,7 @@ class _MihCardsState extends State { showDialog( context: context, barrierDismissible: false, - builder: (context) => MihAddCardWindow( - signedInUser: widget.signedInUser, - cardList: cardList, - ), + builder: (context) => MihAddCardWindow(), ); } @@ -146,9 +137,16 @@ class _MihCardsState extends State { super.dispose(); } + void getLoyaltyCards(BuildContext context) async { + setState(() { + listOfCards = context.read().loyaltyCards; + }); + searchShop(); + } + @override void initState() { - cardList = MIHMzansiWalletApis.getLoyaltyCards(widget.signedInUser.app_id); + getLoyaltyCards(context); cardSearchController.addListener(searchShop); super.initState(); } @@ -187,42 +185,19 @@ class _MihCardsState extends State { ), ), const SizedBox(height: 10), - FutureBuilder( - future: cardList, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center( - child: Mihloadingcircle(), - ); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - listOfCards = snapshot.data!; - searchShop(); - return ValueListenableBuilder( + Consumer( + builder: (context, mzansiWalletProvider, child) { + listOfCards = mzansiWalletProvider.loyaltyCards; + return ValueListenableBuilder>( valueListenable: searchShopName, - builder: (BuildContext context, - List value, Widget? child) { + builder: (context, filteredCards, child) { return BuildLoyaltyCardList( - cardList: value, - signedInUser: widget.signedInUser, + cardList: filteredCards, //listOfCards, navIndex: 0, - bannerAd: _bannerAd, favouritesMode: false, searchText: cardSearchController, - onCardViewClose: () { - setState(() { - _bannerAd = MihBannerAd(); - }); - // Navigator.pop(context); - }, ); - }, - ); - } else { - return const Center( - child: Text("Error Loading Loyalty Cards"), - ); - } + }); }, ), ], diff --git a/Frontend/lib/mih_packages/patient_profile/pat_manager/list_builders/build_mih_patient_search_list.dart b/Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_mih_patient_search_list.dart similarity index 69% rename from Frontend/lib/mih_packages/patient_profile/pat_manager/list_builders/build_mih_patient_search_list.dart rename to Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_mih_patient_search_list.dart index 68f98a06..bcbfb931 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_manager/list_builders/build_mih_patient_search_list.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_mih_patient_search_list.dart @@ -1,38 +1,25 @@ -import 'dart:convert'; import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_access_controls_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_service_calls.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -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_success_message.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_warning_message.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; import 'package:flutter/material.dart'; -import 'package:supertokens_flutter/http.dart' as http; +import 'package:provider/provider.dart'; class BuildMihPatientSearchList extends StatefulWidget { - final List patients; - final AppUser signedInUser; - final Business? business; - final BusinessUser? businessUser; - final bool personalSelected; - const BuildMihPatientSearchList({ super.key, - required this.patients, - required this.signedInUser, - required this.business, - required this.businessUser, - required this.personalSelected, }); @override @@ -48,90 +35,6 @@ class _BuildPatientsListState extends State { TextEditingController accessStatusController = TextEditingController(); final baseAPI = AppEnviroment.baseApiUrl; - Future addPatientAccessAPICall(int index) async { - var response = await http.post( - Uri.parse("$baseAPI/access-requests/insert/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "business_id": widget.business!.business_id, - "app_id": widget.patients[index].app_id, - "date": dateController.text, - "time": timeController.text, - "access": "pending", - }), - ); - if (response.statusCode == 201) { - // Navigator.pushNamed(context, '/patient-manager/patient', - // arguments: widget.signedInUser); - String message = - "The appointment has been successfully booked!\n\nAn approval request as been sent to the patient.Once the access request has been approved, you will be able to access the patients profile. ou can check the status of your request in patient queue under the appointment."; - // "${fnameController.text} ${lnameController.text} patient profiole has been successfully added!\n"; - Navigator.pop(context); - Navigator.pop(context); - setState(() { - dateController.text = ""; - timeController.text = ""; - }); - Navigator.of(context).pushNamed( - '/patient-manager', - arguments: BusinessArguments( - widget.signedInUser, - widget.businessUser, - widget.business, - ), - ); - successPopUp(message); - addAccessReviewNotificationAPICall(index); - } else { - internetConnectionPopUp(); - } - } - - Future addAccessReviewNotificationAPICall(int index) async { - var response = await http.post( - Uri.parse("$baseAPI/notifications/insert/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "app_id": widget.patients[index].app_id, - "notification_type": "New Appointment Booked", - "notification_message": - "A new Appointment has been booked by ${widget.business!.Name} for the ${dateController.text} ${timeController.text}. Please approve the Access Review request.", - "action_path": "/mih-access", - }), - ); - if (response.statusCode == 201) { - // Navigator.pushNamed(context, '/patient-manager/patient', - // arguments: widget.signedInUser); - } else { - internetConnectionPopUp(); - } - } - - void internetConnectionPopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); - } - - void successPopUp(String message) { - showDialog( - context: context, - builder: (context) { - return MIHSuccessMessage( - successType: "Success", - successMessage: message, - ); - }, - ); - } - void noAccessWarning() { showDialog( context: context, @@ -141,10 +44,12 @@ class _BuildPatientsListState extends State { ); } - Future hasAccessToProfile(int index) async { + Future hasAccessToProfile(MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, int index) async { var hasAccess = false; await MIHApiCalls.checkBusinessAccessToPatient( - widget.business!.business_id, widget.patients[index].app_id) + profileProvider.business!.business_id, + patientManagerProvider.patientSearchResults[index].app_id) .then((results) { if (results.isEmpty) { setState(() { @@ -163,10 +68,12 @@ class _BuildPatientsListState extends State { return hasAccess; } - Future getAccessStatusOfProfile(int index) async { + Future getAccessStatusOfProfile(MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, int index) async { var accessStatus = ""; await MIHApiCalls.checkBusinessAccessToPatient( - widget.business!.business_id, widget.patients[index].app_id) + profileProvider.business!.business_id, + patientManagerProvider.patientSearchResults[index].app_id) .then((results) { if (results.isEmpty) { setState(() { @@ -181,15 +88,22 @@ class _BuildPatientsListState extends State { return accessStatus; } - void patientProfileChoicePopUp(int index) async { + void patientProfileChoicePopUp( + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + int index, + ) async { var hasAccess = false; String accessStatus = ""; - await hasAccessToProfile(index).then((result) { + await hasAccessToProfile(profileProvider, patientManagerProvider, index) + .then((result) { setState(() { hasAccess = result; }); }); - await getAccessStatusOfProfile(index).then((result) { + await getAccessStatusOfProfile( + profileProvider, patientManagerProvider, index) + .then((result) { setState(() { accessStatus = result; }); @@ -197,13 +111,22 @@ class _BuildPatientsListState extends State { if (accessStatus == "") { accessStatus = "No Access"; } - var idStars = '*' * (13 - 6); - String startedOutPatientIdNo = - "${widget.patients[index].id_no.substring(0, 6)}$idStars"; + String patientIdNo = + patientManagerProvider.patientSearchResults[index].id_no; + String displayedIdNo; + + if (patientIdNo.length >= 6) { + var idStars = '*' * (patientIdNo.length - 6); + displayedIdNo = "${patientIdNo.substring(0, 6)}$idStars"; + } else { + displayedIdNo = "${patientIdNo}******"; + } setState(() { - idController.text = startedOutPatientIdNo; - fnameController.text = widget.patients[index].first_name; - lnameController.text = widget.patients[index].last_name; + idController.text = displayedIdNo; + fnameController.text = + patientManagerProvider.patientSearchResults[index].first_name; + lnameController.text = + patientManagerProvider.patientSearchResults[index].last_name; accessStatusController.text = accessStatus.toUpperCase(); }); //print(accessStatus); @@ -362,17 +285,21 @@ class _BuildPatientsListState extends State { visible: hasAccess, child: Center( child: MihButton( - onPressed: () { + onPressed: () async { if (hasAccess) { + await MihPatientServices().getPatientDetails( + patientManagerProvider + .patientSearchResults[index].app_id, + patientManagerProvider); context.pop(); - context.pushNamed('patientManagerPatient', - extra: PatientViewArguments( - widget.signedInUser, - widget.patients[index], - widget.businessUser, - widget.business, - "business", - )); + context.pushNamed( + 'patientManagerPatient', + ); + // context.pushNamed( + // 'patientPatient', + // extra: patientManagerProvider + // .patientSearchResults![index].app_id, + // ); // Navigator.of(context) // .pushNamed('/patient-manager/patient', // arguments: PatientViewArguments( @@ -407,17 +334,19 @@ class _BuildPatientsListState extends State { visible: !hasAccess && accessStatus == "No Access", child: Center( child: MihButton( - onPressed: () { - MIHApiCalls.addPatientAccessAPICall( - widget.business!.business_id, - widget.patients[index].app_id, + onPressed: () async { + await MihAccessControlsServices + .addPatientAccessAPICall( + profileProvider.business!.business_id, + patientManagerProvider + .patientSearchResults[index].app_id, "patient", - widget.business!.Name, - widget.personalSelected, + profileProvider.business!.Name, + patientManagerProvider.personalMode, BusinessArguments( - widget.signedInUser, - widget.businessUser, - widget.business, + profileProvider.user!, + profileProvider.businessUser, + profileProvider.business, ), context, ); @@ -443,15 +372,16 @@ class _BuildPatientsListState extends State { visible: !hasAccess && accessStatus == "declined", child: Center( child: MihButton( - onPressed: () { - MIHApiCalls.reapplyPatientAccessAPICall( - widget.business!.business_id, - widget.patients[index].app_id, - widget.personalSelected, + onPressed: () async { + await MIHApiCalls.reapplyPatientAccessAPICall( + profileProvider.business!.business_id, + patientManagerProvider + .patientSearchResults[index].app_id, + patientManagerProvider.personalMode, BusinessArguments( - widget.signedInUser, - widget.businessUser, - widget.business, + profileProvider.user!, + profileProvider.businessUser, + profileProvider.business, ), context, ); @@ -491,20 +421,17 @@ class _BuildPatientsListState extends State { ); } - Widget isMainMember(int index) { - //var matchRE = RegExp(r'^[a-z]+$'); - // var firstLetterFName = widget.patients[index].first_name[0]; - // var firstLetterLName = widget.patients[index].last_name[0]; - // var fnameStar = '*' * 8; - // var lnameStar = '*' * 8; - - if (widget.patients[index].medical_aid_main_member == "Yes") { + Widget isMainMember( + PatientManagerProvider patientManagerProvider, int index) { + if (patientManagerProvider + .patientSearchResults[index].medical_aid_main_member == + "Yes") { return Row( mainAxisSize: MainAxisSize.max, children: [ Text( // "$firstLetterFName$fnameStar $firstLetterLName$lnameStar", - "${widget.patients[index].first_name} ${widget.patients[index].last_name}", + "${patientManagerProvider.patientSearchResults[index].first_name} ${patientManagerProvider.patientSearchResults[index].last_name}", style: TextStyle( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -523,7 +450,7 @@ class _BuildPatientsListState extends State { } else { return Text( // "$firstLetterFName$fnameStar $firstLetterLName$lnameStar", - "${widget.patients[index].first_name} ${widget.patients[index].last_name}", + "${patientManagerProvider.patientSearchResults[index].first_name} ${patientManagerProvider.patientSearchResults[index].last_name}", style: TextStyle( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -532,23 +459,37 @@ class _BuildPatientsListState extends State { } } - Widget hasMedicalAid(int index) { + Widget hasMedicalAid( + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + int index, + ) { + String patientIdNo = + patientManagerProvider.patientSearchResults[index].id_no; + String displayedIdNo; var medAidNoStar = '*' * 8; - var idStars = '*' * (13 - 6); - String startedOutPatientIdNo = - "${widget.patients[index].id_no.substring(0, 6)}$idStars"; - if (widget.patients[index].medical_aid == "Yes") { + if (patientIdNo.length >= 6) { + var idStars = '*' * (patientIdNo.length - 6); + displayedIdNo = "${patientIdNo.substring(0, 6)}$idStars"; + } else { + // If ID is shorter than 6 characters, just show it with stars + displayedIdNo = "${patientIdNo}******"; + } + + if (patientManagerProvider.patientSearchResults[index].medical_aid == + "Yes") { return ListTile( - title: isMainMember(index), + title: isMainMember(patientManagerProvider, index), subtitle: Text( - "ID No.: $startedOutPatientIdNo\nMedical Aid No.: $medAidNoStar", + "ID No.: $displayedIdNo\nMedical Aid No.: $medAidNoStar", style: TextStyle( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), ), onTap: () { - patientProfileChoicePopUp(index); + patientProfileChoicePopUp( + profileProvider, patientManagerProvider, index); // setState(() { // appointmentPopUp(index); // // Add popup to add patienmt to queue @@ -565,16 +506,17 @@ class _BuildPatientsListState extends State { ); } else { return ListTile( - title: isMainMember(index), + title: isMainMember(patientManagerProvider, index), subtitle: Text( - "ID No.: $startedOutPatientIdNo\nMedical Aid No.: $medAidNoStar", + "ID No.: $displayedIdNo\nMedical Aid No.: $medAidNoStar", style: TextStyle( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), ), onTap: () { - patientProfileChoicePopUp(index); + patientProfileChoicePopUp( + profileProvider, patientManagerProvider, index); // setState(() { // appointmentPopUp(index); // // Navigator.of(context).pushNamed('/patient-manager/patient', @@ -599,26 +541,35 @@ class _BuildPatientsListState extends State { fnameController.dispose(); lnameController.dispose(); accessStatusController.dispose(); + PatientManagerProvider patientManagerProvider = + context.read(); + patientManagerProvider.setPatientSearchResults(patientSearchResults: []); super.dispose(); } @override Widget build(BuildContext context) { - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - separatorBuilder: (BuildContext context, index) { - return Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, index) { + return Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + itemCount: patientManagerProvider.patientSearchResults.length, + itemBuilder: (context, index) { + KenLogger.success( + "Search Results Count: ${patientManagerProvider.patientSearchResults.length}"); + return hasMedicalAid( + profileProvider, patientManagerProvider, index); + }, ); }, - itemCount: widget.patients.length, - itemBuilder: (context, index) { - //final patient = widget.patients[index].id_no.contains(widget.searchString); - //print(index); - return hasMedicalAid(index); - }, ); } } diff --git a/Frontend/lib/mih_packages/patient_profile/pat_manager/list_builders/build_my_patient_list_list.dart b/Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_my_patient_list_list.dart similarity index 78% rename from Frontend/lib/mih_packages/patient_profile/pat_manager/list_builders/build_my_patient_list_list.dart rename to Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_my_patient_list_list.dart index d7e6059a..c588abf5 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_manager/list_builders/build_my_patient_list_list.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_my_patient_list_list.dart @@ -1,9 +1,11 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_service_calls.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_calendar_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; @@ -15,26 +17,12 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ 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_warning_message.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class BuildMyPatientListList extends StatefulWidget { - final List patientAccesses; - final AppUser signedInUser; - final Business? business; - final BusinessUser? businessUser; - const BuildMyPatientListList({ super.key, - required this.patientAccesses, - required this.signedInUser, - required this.business, - required this.businessUser, }); @override @@ -51,24 +39,21 @@ class _BuildPatientsListState extends State { final baseAPI = AppEnviroment.baseApiUrl; - Future submitApointment(int index) async { + Future submitApointment(MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, int index) async { //To-Do: Add the appointment to the database // print("To-Do: Add the appointment to the database"); String description = "Date: ${dateController.text}\nTime: ${timeController.text}\n"; - description += "Medical Practice: ${widget.business!.Name}\n"; - description += "Contact Number: ${widget.business!.contact_no}"; + description += "Medical Practice: ${profileProvider.business!.Name}\n"; + description += "Contact Number: ${profileProvider.business!.contact_no}"; int statusCode; statusCode = await MihMzansiCalendarApis.addPatientAppointment( - widget.signedInUser, + profileProvider.user!, false, - widget.patientAccesses[index].app_id, - BusinessArguments( - widget.signedInUser, - widget.businessUser, - widget.business, - ), - "${widget.patientAccesses[index].fname} ${widget.patientAccesses[index].lname} - Doctors Visit", + patientManagerProvider.myPaitentList![index].app_id, + profileProvider.business!.business_id, + "${patientManagerProvider.myPaitentList![index].fname} ${patientManagerProvider.myPaitentList![index].lname} - Doctors Visit", description, dateController.text, timeController.text, @@ -164,11 +149,16 @@ class _BuildPatientsListState extends State { } } - void appointmentPopUp(int index, double width) { - var firstLetterFName = widget.patientAccesses[index].fname; - var firstLetterLName = widget.patientAccesses[index].lname; + void appointmentPopUp( + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + int index, + double width, + ) { + var firstLetterFName = patientManagerProvider.myPaitentList![index].fname; + var firstLetterLName = patientManagerProvider.myPaitentList![index].lname; setState(() { - idController.text = widget.patientAccesses[index].id_no; + idController.text = patientManagerProvider.myPaitentList![index].id_no; fnameController.text = firstLetterFName; lnameController.text = firstLetterLName; }); @@ -260,7 +250,8 @@ class _BuildPatientsListState extends State { if (_formKey.currentState!.validate()) { bool filled = isAppointmentFieldsFilled(); if (filled) { - submitApointment(index); + submitApointment( + profileProvider, patientManagerProvider, index); } else { showDialog( context: context, @@ -299,8 +290,9 @@ class _BuildPatientsListState extends State { ); } - void noAccessWarning(int index) { - if (widget.patientAccesses[index].status == "pending") { + void noAccessWarning( + PatientManagerProvider patientManagerProvider, int index) { + if (patientManagerProvider.myPaitentList![index].status == "pending") { showDialog( context: context, builder: (context) { @@ -317,10 +309,11 @@ class _BuildPatientsListState extends State { } } - bool hasAccessToProfile(int index) { + bool hasAccessToProfile( + PatientManagerProvider patientManagerProvider, int index) { var hasAccess = false; - if (widget.patientAccesses[index].status == "approved") { + if (patientManagerProvider.myPaitentList![index].status == "approved") { hasAccess = true; } else { hasAccess = false; @@ -329,11 +322,15 @@ class _BuildPatientsListState extends State { } void patientProfileChoicePopUp( - int index, Patient? patientProfile, double width) async { - var firstLetterFName = widget.patientAccesses[index].fname; - var firstLetterLName = widget.patientAccesses[index].lname; + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + int index, + double width, + ) async { + var firstLetterFName = patientManagerProvider.myPaitentList![index].fname; + var firstLetterLName = patientManagerProvider.myPaitentList![index].lname; setState(() { - idController.text = widget.patientAccesses[index].id_no; + idController.text = patientManagerProvider.myPaitentList![index].id_no; fnameController.text = firstLetterFName; lnameController.text = firstLetterLName; }); @@ -405,7 +402,8 @@ class _BuildPatientsListState extends State { children: [ MihButton( onPressed: () { - appointmentPopUp(index, width); + appointmentPopUp(profileProvider, + patientManagerProvider, index, width); }, buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == @@ -423,25 +421,14 @@ class _BuildPatientsListState extends State { ), ), MihButton( - onPressed: () { + onPressed: () async { + await MihPatientServices().getPatientDetails( + patientManagerProvider.myPaitentList![index].app_id, + patientManagerProvider); context.pop(); - context.pushNamed('patientManagerPatient', - extra: PatientViewArguments( - widget.signedInUser, - patientProfile, - widget.businessUser, - widget.business, - "business", - )); - // Navigator.of(context) - // .pushNamed('/patient-manager/patient', - // arguments: PatientViewArguments( - // widget.signedInUser, - // patientProfile, - // widget.businessUser, - // widget.business, - // "business", - // )); + context.pushNamed( + 'patientManagerPatient', + ); }, buttonColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == @@ -468,33 +455,43 @@ class _BuildPatientsListState extends State { ); } - Widget displayMyPatientTile(int index, double width) { + Widget displayMyPatientTile( + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + int index, + double width, + ) { var firstName = ""; var lastName = ""; - String access = widget.patientAccesses[index].status.toUpperCase(); + String access = + patientManagerProvider.myPaitentList![index].status.toUpperCase(); TextSpan accessWithColour; var hasAccess = false; - hasAccess = hasAccessToProfile(index); + hasAccess = hasAccessToProfile(patientManagerProvider, index); //print(hasAccess); if (access == "APPROVED") { - firstName = widget.patientAccesses[index].fname; - lastName = widget.patientAccesses[index].lname; + firstName = patientManagerProvider.myPaitentList![index].fname; + lastName = patientManagerProvider.myPaitentList![index].lname; accessWithColour = TextSpan( text: "$access\n", style: TextStyle( color: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"))); } else if (access == "PENDING") { - firstName = "${widget.patientAccesses[index].fname[0]}********"; - lastName = "${widget.patientAccesses[index].lname[0]}********"; + firstName = + "${patientManagerProvider.myPaitentList![index].fname[0]}********"; + lastName = + "${patientManagerProvider.myPaitentList![index].lname[0]}********"; accessWithColour = TextSpan( text: "$access\n", style: TextStyle( color: MihColors.getGreyColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"))); } else { - firstName = "${widget.patientAccesses[index].fname[0]}********"; - lastName = "${widget.patientAccesses[index].lname[0]}********"; + firstName = + "${patientManagerProvider.myPaitentList![index].fname[0]}********"; + lastName = + "${patientManagerProvider.myPaitentList![index].lname[0]}********"; accessWithColour = TextSpan( text: "$access\n", style: TextStyle( @@ -512,7 +509,8 @@ class _BuildPatientsListState extends State { ), subtitle: RichText( text: TextSpan( - text: "ID No.: ${widget.patientAccesses[index].id_no}\n", + text: + "ID No.: ${patientManagerProvider.myPaitentList![index].id_no}\n", style: DefaultTextStyle.of(context).style, children: [ const TextSpan(text: "Access: "), @@ -520,18 +518,16 @@ class _BuildPatientsListState extends State { ]), ), onTap: () async { - Patient? p; if (hasAccess) { - await MIHApiCalls.fetchPatientByAppId( - widget.patientAccesses[index].app_id) - .then((result) { - setState(() { - p = result; - }); - }); - patientProfileChoicePopUp(index, p, width); + await MihPatientServices() + .getPatientDetails( + patientManagerProvider.myPaitentList![index].app_id, + patientManagerProvider) + .then((result) {}); + patientProfileChoicePopUp( + profileProvider, patientManagerProvider, index, width); } else { - noAccessWarning(index); + noAccessWarning(patientManagerProvider, index); } }, trailing: Icon( @@ -555,19 +551,25 @@ class _BuildPatientsListState extends State { @override Widget build(BuildContext context) { double screenWidth = MediaQuery.of(context).size.width; - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - separatorBuilder: (BuildContext context, index) { - return Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, index) { + return Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + itemCount: patientManagerProvider.myPaitentList!.length, + itemBuilder: (context, index) { + return displayMyPatientTile( + profileProvider, patientManagerProvider, index, screenWidth); + }, ); }, - itemCount: widget.patientAccesses.length, - itemBuilder: (context, index) { - return displayMyPatientTile(index, screenWidth); - }, ); } } diff --git a/Frontend/lib/mih_packages/patient_profile/pat_manager/list_builders/build_waiting_room_list.dart b/Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_waiting_room_list.dart similarity index 100% rename from Frontend/lib/mih_packages/patient_profile/pat_manager/list_builders/build_waiting_room_list.dart rename to Frontend/lib/mih_packages/patient_manager/pat_manager/list_builders/build_waiting_room_list.dart diff --git a/Frontend/lib/mih_packages/patient_profile/pat_manager/package_tiles/pat_manager_tile.dart b/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tiles/pat_manager_tile.dart similarity index 97% rename from Frontend/lib/mih_packages/patient_profile/pat_manager/package_tiles/pat_manager_tile.dart rename to Frontend/lib/mih_packages/patient_manager/pat_manager/package_tiles/pat_manager_tile.dart index 0d95b243..438f411d 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_manager/package_tiles/pat_manager_tile.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tiles/pat_manager_tile.dart @@ -27,7 +27,6 @@ class _PatManagerTileState extends State { onTap: () { context.goNamed( 'patientManager', - extra: widget.arguments, ); // Navigator.of(context).pushNamed( // '/patient-manager', diff --git a/Frontend/lib/mih_packages/patient_profile/pat_manager/package_tools/mih_patient_search.dart b/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/mih_patient_search.dart similarity index 51% rename from Frontend/lib/mih_packages/patient_profile/pat_manager/package_tools/mih_patient_search.dart rename to Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/mih_patient_search.dart index 92ff42a7..a795732a 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_manager/package_tools/mih_patient_search.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/mih_patient_search.dart @@ -1,32 +1,21 @@ import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_service_calls.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/list_builders/build_mih_patient_search_list.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/list_builders/build_mih_patient_search_list.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MihPatientSearch extends StatefulWidget { - final AppUser signedInUser; - final Business? business; - final BusinessUser? businessUser; - final bool personalSelected; - const MihPatientSearch({ super.key, - required this.signedInUser, - required this.business, - required this.businessUser, - required this.personalSelected, }); @override @@ -40,71 +29,44 @@ class _MihPatientSearchState extends State { bool hasSearchedBefore = false; String _mihPatientSearchString = ""; String baseUrl = AppEnviroment.baseApiUrl; - late Future> _mihPatientSearchResults; Widget getPatientSearch(double width) { - return MihSingleChildScroll( - child: Column(mainAxisSize: MainAxisSize.max, children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: width / 20), - child: MihSearchBar( - controller: _mihPatientSearchController, - hintText: "Search Patient ID/ Aid No.", - prefixIcon: Icons.search, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - hintColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onPrefixIconTap: () { - submitPatientSearch(); - }, - onClearIconTap: () { - setState(() { - _mihPatientSearchController.clear(); - _mihPatientSearchString = ""; - }); - submitPatientSearch(); - //To-Do: Implement the search function - // print("To-Do: Implement the search function"); - }, - searchFocusNode: _searchFocusNode, - ), - ), - //spacer - const SizedBox(height: 10), - FutureBuilder( - future: _mihPatientSearchResults, - builder: (context, snapshot) { - //print("patient Liust ${snapshot.data}"); - if (snapshot.connectionState == ConnectionState.waiting) { - return const Mihloadingcircle(); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - List patientsList; - if (_mihPatientSearchString == "") { - patientsList = []; - } else { - patientsList = filterSearchResults( - snapshot.data!, _mihPatientSearchString); - //print(patientsList); - } - return displayPatientList(patientsList, _mihPatientSearchString); - } else { - return Center( - child: Text( - "Error pulling Patients Data\n$baseUrl/patients/search/$_mihPatientSearchString", - style: TextStyle( - fontSize: 25, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark")), - textAlign: TextAlign.center, - ), - ); - } - }, - ), - ]), + return Consumer( + builder: (BuildContext context, + PatientManagerProvider patientManagerProvider, Widget? child) { + return MihSingleChildScroll( + child: Column(mainAxisSize: MainAxisSize.max, children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: MihSearchBar( + controller: _mihPatientSearchController, + hintText: "Search Patient ID/ Aid No.", + prefixIcon: Icons.search, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + hintColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onPrefixIconTap: () { + submitPatientSearch(patientManagerProvider); + }, + onClearIconTap: () { + setState(() { + _mihPatientSearchController.clear(); + _mihPatientSearchString = ""; + }); + patientManagerProvider + .setPatientSearchResults(patientSearchResults: []); + }, + searchFocusNode: _searchFocusNode, + ), + ), + //spacer + const SizedBox(height: 10), + + displayPatientList(patientManagerProvider, _mihPatientSearchString), + ]), + ); + }, ); } @@ -121,16 +83,12 @@ class _MihPatientSearchState extends State { return templist; } - Widget displayPatientList(List patientsList, String searchString) { - if (patientsList.isNotEmpty) { - return BuildMihPatientSearchList( - patients: patientsList, - signedInUser: widget.signedInUser, - business: widget.business, - businessUser: widget.businessUser, - personalSelected: widget.personalSelected, - ); - } else if (patientsList.isEmpty && searchString != "") { + Widget displayPatientList( + PatientManagerProvider patientManagerProvider, String searchString) { + if (patientManagerProvider.patientSearchResults.isNotEmpty) { + return BuildMihPatientSearchList(); + } else if (patientManagerProvider.patientSearchResults.isEmpty && + searchString != "") { return Column( children: [ const SizedBox(height: 50), @@ -195,17 +153,6 @@ class _MihPatientSearchState extends State { TextSpan( text: "You can search using their ID Number or Medical Aid No."), - // WidgetSpan( - // alignment: PlaceholderAlignment.middle, - // child: Icon( - // Icons.menu, - // size: 20, - // color: MzansiInnovationHub.of(context)! - // .theme - // .secondaryColor(), - // ), - // ), - // TextSpan(text: " to add your first loyalty card"), ], ), ), @@ -213,30 +160,18 @@ class _MihPatientSearchState extends State { ], ), ); - // return Padding( - // padding: const EdgeInsets.only(top: 35.0), - // child: Center( - // child: Text( - // "Enter ID or Medical Aid No. of Patient", - // style: TextStyle( - // fontSize: 25, - // color: - // MihColors.getGreyColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark")), - // textAlign: TextAlign.center, - // ), - // ), - // ); } } - void submitPatientSearch() { + Future submitPatientSearch( + PatientManagerProvider patientManagerProvider) async { if (_mihPatientSearchController.text != "") { setState(() { _mihPatientSearchString = _mihPatientSearchController.text; - _mihPatientSearchResults = - MIHApiCalls.fetchPatients(_mihPatientSearchString); hasSearchedBefore = true; }); + await MihPatientServices.searchPatients( + patientManagerProvider, _mihPatientSearchString); } } @@ -257,7 +192,6 @@ class _MihPatientSearchState extends State { @override void initState() { super.initState(); - _mihPatientSearchResults = MIHApiCalls.fetchPatients("abc"); } @override diff --git a/Frontend/lib/mih_packages/patient_profile/pat_manager/package_tools/my_patient_list.dart b/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/my_patient_list.dart similarity index 67% rename from Frontend/lib/mih_packages/patient_profile/pat_manager/package_tools/my_patient_list.dart rename to Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/my_patient_list.dart index 470a5150..f2b426ee 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_manager/package_tools/my_patient_list.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/my_patient_list.dart @@ -1,31 +1,21 @@ import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_service_calls.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/list_builders/build_my_patient_list_list.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/list_builders/build_my_patient_list_list.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MyPatientList extends StatefulWidget { - final AppUser signedInUser; - final Business? business; - final BusinessUser? businessUser; - final bool personalSelected; - const MyPatientList({ super.key, - required this.signedInUser, - this.business, - this.businessUser, - this.personalSelected = false, }); @override @@ -33,7 +23,6 @@ class MyPatientList extends StatefulWidget { } class _MyPatientListState extends State { - late Future> _myPatientList; TextEditingController _myPatientSearchController = TextEditingController(); final FocusNode _searchFocusNode = FocusNode(); bool hasSearchedBefore = false; @@ -42,7 +31,8 @@ class _MyPatientListState extends State { final FocusNode _focusNode = FocusNode(); - Widget myPatientListTool(double width) { + Widget myPatientListTool(MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, double width) { return MihSingleChildScroll( child: Column(mainAxisSize: MainAxisSize.max, children: [ Padding( @@ -56,10 +46,11 @@ class _MyPatientListState extends State { hintColor: MihColors.getPrimaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onPrefixIconTap: () { - setState(() { + setState(() async { _myPatientIdSearchString = _myPatientSearchController.text; - _myPatientList = MIHApiCalls.getPatientAccessListOfBusiness( - widget.business!.business_id); + await MihPatientServices().getPatientAccessListOfBusiness( + patientManagerProvider, + profileProvider.business!.business_id); }); }, onClearIconTap: () { @@ -67,57 +58,21 @@ class _MyPatientListState extends State { _myPatientSearchController.clear(); _myPatientIdSearchString = ""; }); - getMyPatientList(); + getMyPatientList(profileProvider, patientManagerProvider); }, searchFocusNode: _searchFocusNode, ), ), //spacer const SizedBox(height: 10), - FutureBuilder( - future: _myPatientList, - builder: (context, snapshot) { - //print("patient Liust ${snapshot.data}"); - if (snapshot.connectionState == ConnectionState.waiting) { - return const Mihloadingcircle(); - } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - List patientsAccessList; - if (_myPatientIdSearchString == "") { - patientsAccessList = snapshot.data!; - } else { - patientsAccessList = filterAccessResults( - snapshot.data!, _myPatientIdSearchString); - //print(patientsList); - } - return displayMyPatientList(patientsAccessList); - } else { - return Center( - child: Text( - "Error pulling Patient Access Data\n$baseUrl/access-requests/business/patient/${widget.business!.business_id}", - style: TextStyle( - fontSize: 25, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark")), - textAlign: TextAlign.center, - ), - ); - } - }, - ), + displayMyPatientList(patientManagerProvider), ]), ); } - Widget displayMyPatientList(List patientsAccessList) { - if (patientsAccessList.isNotEmpty) { - return BuildMyPatientListList( - patientAccesses: patientsAccessList, - signedInUser: widget.signedInUser, - business: widget.business, - businessUser: widget.businessUser, - ); + Widget displayMyPatientList(PatientManagerProvider patientManagerProvider) { + if (patientManagerProvider.myPaitentList!.isNotEmpty) { + return BuildMyPatientListList(); } if (hasSearchedBefore && _myPatientIdSearchString.isNotEmpty) { return Column( @@ -228,10 +183,11 @@ class _MyPatientListState extends State { return templist; } - void getMyPatientList() { + Future getMyPatientList(MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider) async { + await MihPatientServices().getPatientAccessListOfBusiness( + patientManagerProvider, profileProvider.business!.business_id); setState(() { - _myPatientList = MIHApiCalls.getPatientAccessListOfBusiness( - widget.business!.business_id); hasSearchedBefore = true; }); } @@ -239,8 +195,6 @@ class _MyPatientListState extends State { @override void initState() { super.initState(); - _myPatientList = MIHApiCalls.getPatientAccessListOfBusiness( - widget.business!.business_id); } @override @@ -256,10 +210,16 @@ class _MyPatientListState extends State { Widget build(BuildContext context) { final Size size = MediaQuery.sizeOf(context); final double width = size.width; - return MihPackageToolBody( - borderOn: false, - innerHorizontalPadding: 10, - bodyItem: myPatientListTool(width), + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + return MihPackageToolBody( + borderOn: false, + innerHorizontalPadding: 10, + bodyItem: + myPatientListTool(profileProvider, patientManagerProvider, width), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/patient_profile/pat_manager/package_tools/waiting_room.dart b/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/waiting_room.dart similarity index 75% rename from Frontend/lib/mih_packages/patient_profile/pat_manager/package_tools/waiting_room.dart rename to Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/waiting_room.dart index 9dfe5cbf..3c407aac 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_manager/package_tools/waiting_room.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_manager/package_tools/waiting_room.dart @@ -3,6 +3,9 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_calendar_services.dart'; @@ -20,26 +23,14 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ 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_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/appointment.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; import 'package:mzansi_innovation_hub/mih_packages/calendar/builder/build_appointment_list.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class WaitingRoom extends StatefulWidget { - final AppUser signedInUser; - final Business? business; - final BusinessUser? businessUser; - final bool personalSelected; - final Function(int) onIndexChange; const WaitingRoom({ super.key, - required this.signedInUser, - required this.business, - required this.businessUser, - required this.personalSelected, - required this.onIndexChange, }); @override @@ -60,113 +51,96 @@ class _WaitingRoomState extends State { final TextEditingController _patientController = TextEditingController(); String baseUrl = AppEnviroment.baseApiUrl; - String selectedDay = DateTime.now().toString().split(" ")[0]; - late Future> businessAppointmentResults; late Future> appointmentResults; bool inWaitingRoom = true; + bool isLoading = true; final _formKey = GlobalKey(); // Business Appointment Tool Widget getBusinessAppointmentsTool(double width) { - return Stack( - children: [ - MihSingleChildScroll( - child: Column( - children: [ - MIHCalendar( - calendarWidth: 500, - rowHeight: 35, - setDate: (value) { - setState(() { - selectedDay = value; - selectedAppointmentDateController.text = selectedDay; - }); - }), - // Divider( - // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - Row( - mainAxisSize: MainAxisSize.max, + return Consumer3( + builder: (BuildContext context, + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + MihCalendarProvider mihCalendarProvider, + Widget? child) { + if (isLoading) { + return const Center( + child: Mihloadingcircle(), + ); + } + return Stack( + children: [ + MihSingleChildScroll( + child: Column( children: [ - FutureBuilder( - future: appointmentResults, - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState.waiting) { - return const Expanded( - child: Center(child: Mihloadingcircle())); - } else if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - return - // Container(child: const Placeholder()); - displayAppointmentList(snapshot.requireData); - } else { - return Center( - child: Text( - "Error pulling appointments", - style: TextStyle( - fontSize: 25, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)! - .theme - .mode == - "Dark")), - textAlign: TextAlign.center, - ), - ); - } + MIHCalendar( + calendarWidth: 500, + rowHeight: 35, + setDate: (value) { + mihCalendarProvider.setSelectedDay(value); + setState(() { + selectedAppointmentDateController.text = value; + }); }), + // Divider( + // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + Row( + mainAxisSize: MainAxisSize.max, + children: [ + displayAppointmentList(mihCalendarProvider), + ], + ) ], - ) - ], - ), - ), - Positioned( - right: 10, - bottom: 10, - child: MihFloatingMenu( - icon: Icons.add, - animatedIcon: AnimatedIcons.menu_close, - children: [ - SpeedDialChild( - child: Icon( - Icons.add, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - label: "Add Appointment", - labelBackgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - labelStyle: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontWeight: FontWeight.bold, - ), - backgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onTap: () { - // addAppointmentWindow(); - appointmentTypeSelection(width); - }, - ) - ], - ), - ), - ], + ), + ), + Positioned( + right: 10, + bottom: 10, + child: MihFloatingMenu( + icon: Icons.add, + animatedIcon: AnimatedIcons.menu_close, + children: [ + SpeedDialChild( + child: Icon( + Icons.add, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + label: "Add Appointment", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onTap: () { + // addAppointmentWindow(); + appointmentTypeSelection(profileProvider, + patientManagerProvider, mihCalendarProvider, width); + }, + ) + ], + ), + ), + ], + ); + }, ); } - Widget displayAppointmentList(List appointmentList) { - if (appointmentList.isNotEmpty) { + Widget displayAppointmentList(MihCalendarProvider mihCalendarProvider) { + if (mihCalendarProvider.businessAppointments!.isNotEmpty) { return Expanded( child: BuildAppointmentList( - appointmentList: appointmentList, - signedInUser: widget.signedInUser, - business: widget.business, - businessUser: widget.businessUser, - personalSelected: widget.personalSelected, inWaitingRoom: true, titleController: _appointmentTitleController, descriptionIDController: _appointmentDescriptionIDController, @@ -192,7 +166,7 @@ class _WaitingRoomState extends State { ), const SizedBox(height: 10), Text( - "No Appointments for $selectedDay", + "No Appointments for ${mihCalendarProvider.selectedDay}", textAlign: TextAlign.center, overflow: TextOverflow.visible, style: TextStyle( @@ -255,7 +229,11 @@ class _WaitingRoomState extends State { // ); } - void appointmentTypeSelection(double width) { + void appointmentTypeSelection( + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + MihCalendarProvider mihCalendarProvider, + double width) { String question = "What type of appointment would you like to add?"; question += "\n\nExisting Patient: Add an appointment for an patient your practice has access to."; @@ -286,7 +264,7 @@ class _WaitingRoomState extends State { const SizedBox(height: 15), MihButton( onPressed: () { - widget.onIndexChange(1); + patientManagerProvider.setPatientManagerIndex(1); context.pop(); }, buttonColor: MihColors.getGreenColor( @@ -305,7 +283,7 @@ class _WaitingRoomState extends State { const SizedBox(height: 10), MihButton( onPressed: () { - widget.onIndexChange(2); + patientManagerProvider.setPatientManagerIndex(2); context.pop(); }, buttonColor: MihColors.getGreenColor( @@ -325,7 +303,8 @@ class _WaitingRoomState extends State { MihButton( onPressed: () { Navigator.pop(context); - addAppointmentWindow(width); + addAppointmentWindow( + profileProvider, mihCalendarProvider, width); }, buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -347,7 +326,8 @@ class _WaitingRoomState extends State { ); } - void addAppointmentWindow(double width) { + void addAppointmentWindow(MzansiProfileProvider profileProvider, + MihCalendarProvider mihCalendarProvider, double width) { showDialog( context: context, barrierDismissible: false, @@ -428,7 +408,8 @@ class _WaitingRoomState extends State { child: MihButton( onPressed: () { if (_formKey.currentState!.validate()) { - addAppointmentCall(); + addAppointmentCall( + profileProvider, mihCalendarProvider); } else { MihAlertServices().formNotFilledCompletely(context); } @@ -459,35 +440,28 @@ class _WaitingRoomState extends State { ); } - Future addAppointmentCall() async { + Future addAppointmentCall(MzansiProfileProvider profileProvider, + MihCalendarProvider mihCalendarProvider) async { if (isAppointmentInputValid()) { int statusCode; - if (widget.personalSelected == false) { - statusCode = await MihMzansiCalendarApis.addBusinessAppointment( - widget.signedInUser, - widget.business!, - widget.businessUser!, - true, - _appointmentTitleController.text, - _appointmentDescriptionIDController.text, - _appointmentDateController.text, - _appointmentTimeController.text, - context, - ); - } else { - statusCode = await MihMzansiCalendarApis.addPersonalAppointment( - widget.signedInUser, - _appointmentTitleController.text, - _appointmentDescriptionIDController.text, - _appointmentDateController.text, - _appointmentTimeController.text, - context, - ); - } + statusCode = await MihMzansiCalendarApis.addBusinessAppointment( + profileProvider.user!, + profileProvider.business!, + profileProvider.businessUser!, + true, + _appointmentTitleController.text, + _appointmentDescriptionIDController.text, + _appointmentDateController.text, + _appointmentTimeController.text, + mihCalendarProvider, + context, + ); + if (statusCode == 201) { context.pop(); successPopUp("Successfully Added Appointment", "You appointment has been successfully added to your calendar."); + _loadInitialAppointments(); } else { internetConnectionPopUp(); } @@ -585,11 +559,24 @@ class _WaitingRoomState extends State { void checkforchange() { setState(() { - appointmentResults = MihMzansiCalendarApis.getBusinessAppointments( - widget.business!.business_id, - true, - selectedDay, - ); + isLoading = true; + }); + _loadInitialAppointments(); + } + + Future _loadInitialAppointments() async { + MzansiProfileProvider mzansiProfileProvider = + context.read(); + MihCalendarProvider mihCalendarProvider = + context.read(); + await MihMzansiCalendarApis.getBusinessAppointments( + mzansiProfileProvider.business!.business_id, + false, + mihCalendarProvider.selectedDay, + mihCalendarProvider, + ); + setState(() { + isLoading = false; }); } @@ -606,12 +593,8 @@ class _WaitingRoomState extends State { @override void initState() { selectedAppointmentDateController.addListener(checkforchange); - setState(() { - appointmentResults = MihMzansiCalendarApis.getBusinessAppointments( - widget.business!.business_id, - true, - selectedDay, - ); + WidgetsBinding.instance.addPostFrameCallback((_) { + _loadInitialAppointments(); }); super.initState(); } diff --git a/Frontend/lib/mih_packages/patient_manager/pat_manager/pat_manager.dart b/Frontend/lib/mih_packages/patient_manager/pat_manager/pat_manager.dart new file mode 100644 index 00000000..ff3add3b --- /dev/null +++ b/Frontend/lib/mih_packages/patient_manager/pat_manager/pat_manager.dart @@ -0,0 +1,133 @@ +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/package_tools/mih_patient_search.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/package_tools/my_patient_list.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/package_tools/waiting_room.dart'; +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_calendar_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; +import 'package:provider/provider.dart'; + +class PatManager extends StatefulWidget { + const PatManager({ + super.key, + }); + + @override + State createState() => _PatManagerState(); +} + +class _PatManagerState extends State { + bool isLoading = true; + + Future initialisePatientData() async { + setState(() { + isLoading = true; + }); + MzansiProfileProvider profileProvider = + context.read(); + PatientManagerProvider patientManagerProvider = + context.read(); + MihCalendarProvider mihCalendarProvider = + context.read(); + patientManagerProvider.setPersonalMode(false); + if (profileProvider.business != null) { + await MihMzansiCalendarApis.getBusinessAppointments( + profileProvider.business!.business_id, + false, + mihCalendarProvider.selectedDay, + mihCalendarProvider, + ); + await MihPatientServices().getPatientAccessListOfBusiness( + patientManagerProvider, profileProvider.business!.business_id); + } + setState(() { + isLoading = false; + }); + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) async { + initialisePatientData(); + }); + } + + @override + Widget build(BuildContext context) { + return MihPackage( + appActionButton: getActionButton(), + appTools: getTools(), + appBody: getToolBody(), + appToolTitles: getToolTitle(), + selectedbodyIndex: + context.watch().patientManagerIndex, + onIndexChange: (newValue) { + context.read().setPatientManagerIndex(newValue); + }, + ); + } + + MihPackageAction getActionButton() { + PatientManagerProvider patientManagerProvider = + context.read(); + return MihPackageAction( + icon: const Icon(Icons.arrow_back), + iconSize: 35, + onTap: () { + patientManagerProvider.setPatientProfileIndex(0); + patientManagerProvider.setPatientManagerIndex(0); + context.goNamed( + 'mihHome', + ); + FocusScope.of(context).unfocus(); + }, + ); + } + + MihPackageTools getTools() { + Map temp = {}; + temp[const Icon(Icons.calendar_month)] = () { + context.read().setPatientManagerIndex(0); + }; + temp[const Icon(Icons.check_box_outlined)] = () { + context.read().setPatientManagerIndex(1); + }; + + temp[const Icon(Icons.search)] = () { + context + .read() + .setPatientSearchResults(patientSearchResults: []); + context.read().setPatientManagerIndex(2); + }; + return MihPackageTools( + tools: temp, + selcetedIndex: + context.watch().patientManagerIndex, + ); + } + + List getToolBody() { + List toolBodies = [ + WaitingRoom(), + MyPatientList(), + MihPatientSearch(), + ]; + return toolBodies; + } + + List getToolTitle() { + List toolTitles = [ + "Waiting Room", + "My Patients", + "Search Patients", + ]; + return toolTitles; + } +} diff --git a/Frontend/lib/mih_packages/patient_manager/pat_profile/components/claim_statement_window.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/components/claim_statement_window.dart new file mode 100644 index 00000000..aec587b9 --- /dev/null +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/components/claim_statement_window.dart @@ -0,0 +1,564 @@ +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_claim_statement_generation_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_icd10_code_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_date_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_radio_options.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/icd10_code.dart.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/components/icd10_search_window.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +class ClaimStatementWindow extends StatefulWidget { + const ClaimStatementWindow({ + super.key, + }); + + @override + State createState() => _ClaimStatementWindowState(); +} + +class _ClaimStatementWindowState extends State { + final TextEditingController _docTypeController = TextEditingController(); + final TextEditingController _fullNameController = TextEditingController(); + final TextEditingController _idController = TextEditingController(); + final TextEditingController _medAidController = TextEditingController(); + final TextEditingController _medAidNoController = TextEditingController(); + final TextEditingController _medAidCodeController = TextEditingController(); + final TextEditingController _medAidNameController = TextEditingController(); + final TextEditingController _medAidSchemeController = TextEditingController(); + final TextEditingController _providerNameController = TextEditingController(); + final TextEditingController _practiceNoController = TextEditingController(); + final TextEditingController _vatNoController = TextEditingController(); + final TextEditingController _serviceDateController = TextEditingController(); + final TextEditingController _serviceDescController = TextEditingController(); + final TextEditingController _serviceDescOptionsController = + TextEditingController(); + final TextEditingController _prcedureNameController = TextEditingController(); + // final TextEditingController _procedureDateController = + // TextEditingController(); + final TextEditingController _proceedureAdditionalInfoController = + TextEditingController(); + final TextEditingController _icd10CodeController = TextEditingController(); + final TextEditingController _amountController = TextEditingController(); + final TextEditingController _preauthNoController = TextEditingController(); + final ValueNotifier serviceDesc = ValueNotifier(""); + final ValueNotifier medAid = ValueNotifier(""); + List icd10codeList = []; + final FocusNode _searchFocusNode = FocusNode(); + final _formKey = GlobalKey(); + + void icd10SearchWindow(List codeList) { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => ICD10SearchWindow( + icd10CodeController: _icd10CodeController, + icd10codeList: codeList, + ), + ); + } + + Widget getWindowBody(double width) { + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + return Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: width * 0.05) + : const EdgeInsets.symmetric(horizontal: 0), + child: Column( + children: [ + MihForm( + formKey: _formKey, + formFields: [ + MihRadioOptions( + controller: _docTypeController, + hintText: "Document Type", + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + secondaryFillColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + requiredText: true, + radioOptions: const ["Claim", "Statement"], + ), + const SizedBox(height: 10), + Center( + child: Text( + "Service Details", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark")), + const SizedBox(height: 10), + MihDateField( + controller: _serviceDateController, + labelText: "Date of Service", + required: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10), + MihRadioOptions( + controller: _serviceDescController, + hintText: "Serviced Description", + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + secondaryFillColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + requiredText: true, + radioOptions: const [ + "Consultation", + "Procedure", + "Other", + ], + ), + const SizedBox(height: 10), + ValueListenableBuilder( + valueListenable: serviceDesc, + builder: + (BuildContext context, String value, Widget? child) { + Widget returnWidget; + switch (value) { + case 'Consultation': + returnWidget = Column( + key: const ValueKey( + 'consultation_fields'), // Added key + children: [ + MihRadioOptions( + key: const ValueKey( + 'consultation_type_dropdown'), + controller: _serviceDescOptionsController, + hintText: "Consultation Type", + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + secondaryFillColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + requiredText: true, + radioOptions: const [ + "General Consultation", + "Follow-Up Consultation", + "Specialist Consultation", + "Emergency Consultation", + ], + ), + const SizedBox(height: 10), + ], + ); + break; + case 'Procedure': + returnWidget = Column( + key: + const ValueKey('procedure_fields'), // Added key + children: [ + MihTextFormField( + key: const ValueKey( + 'procedure_name_field'), // Added key + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + controller: _prcedureNameController, + multiLineInput: false, + requiredText: true, + hintText: "Procedure Name", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10), + MihTextFormField( + key: const ValueKey( + 'procedure_additional_info_field'), // Added key + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + controller: _proceedureAdditionalInfoController, + multiLineInput: false, + requiredText: true, + hintText: "Additional Procedure Information", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 15), + ], + ); + break; + case 'Other': + returnWidget = Column( + key: const ValueKey('other_fields'), // Added key + children: [ + MihTextFormField( + key: const ValueKey( + 'other_service_description_field'), // Added key + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + controller: _serviceDescOptionsController, + multiLineInput: false, + requiredText: true, + hintText: "Service Description Details", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10), + ], + ); + break; + default: + returnWidget = const SizedBox( + key: const ValueKey('empty_fields')); // Added key + } + return returnWidget; + }, + ), + Column( + children: [ + Align( + alignment: Alignment.centerLeft, + child: Text("ICD-10 Code & Description", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + )), + ), + const SizedBox(height: 4), + MihSearchBar( + controller: _icd10CodeController, + hintText: "ICD-10 Search", + prefixIcon: Icons.search, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + hintColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onPrefixIconTap: () { + MIHIcd10CodeApis.getIcd10Codes( + _icd10CodeController.text, context) + .then((result) { + icd10SearchWindow(result); + }); + }, + onClearIconTap: () { + _icd10CodeController.clear(); + }, + searchFocusNode: _searchFocusNode, + ), + ], + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + controller: _amountController, + multiLineInput: false, + requiredText: true, + numberMode: true, + hintText: "Service Cost", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10), + Center( + child: Text( + "Additional Infomation", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark")), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + controller: _preauthNoController, + multiLineInput: false, + requiredText: false, + hintText: "Pre-authorisation No.", + ), + const SizedBox(height: 20), + Center( + child: MihButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + if (isInputValid()) { + MIHClaimStatementGenerationApi() + .generateClaimStatement( + profileProvider, + patientManagerProvider, + ClaimStatementGenerationArguments( + _docTypeController.text, + patientManagerProvider + .selectedPatient!.app_id, + _fullNameController.text, + _idController.text, + _medAidController.text, + _medAidNoController.text, + _medAidCodeController.text, + _medAidNameController.text, + _medAidSchemeController.text, + profileProvider.business!.Name, + "*To-Be Added*", + profileProvider.business!.contact_no, + profileProvider.business!.bus_email, + _providerNameController.text, + _practiceNoController.text, + _vatNoController.text, + _serviceDateController.text, + _serviceDescController.text, + _serviceDescOptionsController.text, + _prcedureNameController.text, + _proceedureAdditionalInfoController.text, + _icd10CodeController.text, + _amountController.text, + _preauthNoController.text, + profileProvider.business!.logo_path, + profileProvider.businessUser!.sig_path, + ), + AppEnviroment.getEnv(), + context); + } else { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage( + errorType: "Input Error"); + }, + ); + } + } else { + MihAlertServices().formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Generate", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ], + ), + ); + }, + ); + } + + void serviceDescriptionSelected() { + String selectedType = _serviceDescController.text; + serviceDesc.value = selectedType; + if (selectedType == 'Consultation') { + _prcedureNameController.clear(); + _proceedureAdditionalInfoController.clear(); + } else if (selectedType == 'Procedure') { + _serviceDescOptionsController.clear(); + } else if (selectedType == 'Other') { + _prcedureNameController.clear(); + _proceedureAdditionalInfoController.clear(); + } else { + _prcedureNameController.clear(); + _proceedureAdditionalInfoController.clear(); + _serviceDescOptionsController.clear(); + } + } + + void hasMedAid() { + if (_medAidController.text.isNotEmpty) { + } else { + medAid.value = ""; + } + } + + bool isInputValid() { + if (_docTypeController.text.isEmpty || + _serviceDateController.text.isEmpty || + _icd10CodeController.text.isEmpty || + _amountController.text.isEmpty) { + return false; + } + switch (_serviceDescController.text) { + case 'Consultation': + case 'Other': + if (_serviceDescOptionsController.text.isEmpty) { + return false; + } + break; + case 'Procedure': + if (_prcedureNameController.text.isEmpty || + _proceedureAdditionalInfoController.text.isEmpty) { + return false; + } + break; + default: + return false; + } + return true; + } + + String getUserTitle(MzansiProfileProvider profileProvider) { + if (profileProvider.businessUser!.title == "Doctor") { + return "Dr."; + } else { + return profileProvider.businessUser!.title; + } + } + + String getTodayDate() { + DateTime today = DateTime.now(); + return DateFormat('yyyy-MM-dd').format(today); + } + + @override + void dispose() { + _docTypeController.dispose(); + _fullNameController.dispose(); + _idController.dispose(); + _medAidController.dispose(); + _medAidNoController.dispose(); + _medAidCodeController.dispose(); + _medAidNameController.dispose(); + _medAidSchemeController.dispose(); + _providerNameController.dispose(); + _practiceNoController.dispose(); + _vatNoController.dispose(); + _serviceDateController.dispose(); + _serviceDescController.dispose(); + _serviceDescOptionsController.dispose(); + _prcedureNameController.dispose(); + // _procedureDateController.dispose(); + _proceedureAdditionalInfoController.dispose(); + _icd10CodeController.dispose(); + _preauthNoController.dispose(); + _searchFocusNode.dispose(); + serviceDesc.dispose(); + medAid.dispose(); + super.dispose(); + } + + @override + void initState() { + super.initState(); + PatientManagerProvider patientManagerProvider = + context.read(); + MzansiProfileProvider profileProvider = + context.read(); + _serviceDescController.text = "Consultation"; + _serviceDescController.addListener(serviceDescriptionSelected); + serviceDesc.value = "Consultation"; + _medAidController.addListener(hasMedAid); + _fullNameController.text = + "${patientManagerProvider.selectedPatient!.first_name} ${patientManagerProvider.selectedPatient!.last_name}"; + _idController.text = patientManagerProvider.selectedPatient!.id_no; + _medAidController.text = + patientManagerProvider.selectedPatient!.medical_aid; + _medAidNameController.text = + patientManagerProvider.selectedPatient!.medical_aid_name; + _medAidCodeController.text = + patientManagerProvider.selectedPatient!.medical_aid_code; + _medAidNoController.text = + patientManagerProvider.selectedPatient!.medical_aid_no; + _medAidSchemeController.text = + patientManagerProvider.selectedPatient!.medical_aid_scheme; + _serviceDateController.text = getTodayDate(); + _providerNameController.text = + "${getUserTitle(profileProvider)} ${profileProvider.user!.fname} ${profileProvider.user!.lname}"; + _practiceNoController.text = profileProvider.business!.practice_no; + _vatNoController.text = profileProvider.business!.vat_no; + hasMedAid(); + } + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return MihPackageWindow( + fullscreen: false, + windowTitle: "Generate Claim/ Statement Document", + onWindowTapClose: () { + Navigator.pop(context); + }, + windowBody: getWindowBody(screenWidth), + ); + } +} diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/components/full_screen_file.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/components/full_screen_file.dart similarity index 100% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/components/full_screen_file.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/components/full_screen_file.dart diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/components/icd10_search_window.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/components/icd10_search_window.dart similarity index 95% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/components/icd10_search_window.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/components/icd10_search_window.dart index eaffd071..c6699842 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/components/icd10_search_window.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/components/icd10_search_window.dart @@ -4,7 +4,7 @@ import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart' import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/icd10_code.dart.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/list_builders/build_icd10_code_list.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_icd10_code_list.dart'; import 'package:flutter/material.dart'; class ICD10SearchWindow extends StatefulWidget { diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/components/medicine_search.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/components/medicine_search.dart similarity index 96% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/components/medicine_search.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/components/medicine_search.dart index 56a8886e..f3420c85 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/components/medicine_search.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/components/medicine_search.dart @@ -4,7 +4,7 @@ import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_err import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/medicine.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/list_builders/build_med_list.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_med_list.dart'; import 'package:flutter/material.dart'; import 'package:supertokens_flutter/http.dart' as http; diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/patient_add.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/components/mih_edit_patient_details_window.dart similarity index 76% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/patient_add.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/components/mih_edit_patient_details_window.dart index 3863c927..87defc63 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/patient_add.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/components/mih_edit_patient_details_window.dart @@ -1,39 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; -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_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; -class AddPatient extends StatefulWidget { - final AppUser signedInUser; - - const AddPatient({ - super.key, - required this.signedInUser, - }); +class MihEditPatientDetailsWindow extends StatefulWidget { + const MihEditPatientDetailsWindow({super.key}); @override - State createState() => _AddPatientState(); + State createState() => + _MihEditPatientDetailsWindowState(); } -class _AddPatientState extends State { - final idController = TextEditingController(); +class _MihEditPatientDetailsWindowState + extends State { + var idController = TextEditingController(); final fnameController = TextEditingController(); final lnameController = TextEditingController(); final cellController = TextEditingController(); @@ -45,51 +37,16 @@ class _AddPatientState extends State { final medAidController = TextEditingController(); final medMainMemController = TextEditingController(); final medAidCodeController = TextEditingController(); - - late bool medAidPosition; - late bool medMainMemberPosition; - final baseAPI = AppEnviroment.baseApiUrl; - late int futureDocOfficeId; - //late bool medRequired; - final ValueNotifier medRequired = ValueNotifier(false); final FocusNode _focusNode = FocusNode(); final _formKey = GlobalKey(); + late bool medAidPosition; + late bool medMainMemberPosition; + final ValueNotifier medRequired = ValueNotifier(false); - bool isFieldsFilled() { - if (medRequired.value) { - if (idController.text.isEmpty || - fnameController.text.isEmpty || - lnameController.text.isEmpty || - cellController.text.isEmpty || - emailController.text.isEmpty || - medNoController.text.isEmpty || - medNameController.text.isEmpty || - medSchemeController.text.isEmpty || - addressController.text.isEmpty || - medAidController.text.isEmpty || - medMainMemController.text.isEmpty || - medAidCodeController.text.isEmpty) { - return false; - } else { - return true; - } - } else { - if (idController.text.isEmpty || - fnameController.text.isEmpty || - lnameController.text.isEmpty || - cellController.text.isEmpty || - emailController.text.isEmpty || - addressController.text.isEmpty || - medAidController.text.isEmpty) { - return false; - } else { - return true; - } - } - } - - Future addPatientService() async { - int statusCode = await MihPatientServices().addPatientService( + Future updatePatientApiCall( + PatientManagerProvider patientManagerProvider) async { + var statusCode = await MihPatientServices().updatePatientService( + patientManagerProvider.selectedPatient!.app_id, idController.text, fnameController.text, lnameController.text, @@ -102,14 +59,19 @@ class _AddPatientState extends State { medNameController.text, medSchemeController.text, addressController.text, - widget.signedInUser, + patientManagerProvider, ); - if (statusCode == 201) { - String message = - "${fnameController.text} ${lnameController.text} patient profile has been successfully added!\n"; - successPopUp("Successfully created Patient Profile", message); + if (statusCode == 200) { + successPopUp( + "Successfully Updated Profile!", + "${fnameController.text} ${lnameController.text}'s information has been updated successfully! Their medical records and details are now current.", + ); } else { - internetConnectionPopUp(); + MihAlertServices().errorAlert( + "Error Updating Profile", + "There was an error updating your profile. Please try again later.", + context, + ); } } @@ -140,17 +102,18 @@ class _AddPatientState extends State { Center( child: MihButton( onPressed: () { + // context.goNamed( + // "patientProfile", + // extra: PatientViewArguments( + // widget.signedInUser, + // widget.selectedPatient, + // null, + // null, + // "personal", + // ), + // ); + context.pop(); context.pop(); - context.goNamed( - 'patientProfile', - extra: PatientViewArguments( - widget.signedInUser, - null, - null, - null, - "personal", - ), - ); }, buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -173,45 +136,21 @@ class _AddPatientState extends State { alertColour: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ); + // return MIHSuccessMessage( + // successType: "Success", + // successMessage: message, + // ); }, ); } - void internetConnectionPopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); - } - - void messagePopUp(error) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text(error), - ); - }, - ); - } - - void isRequired() { - //print("listerner triggered"); - if (medAidController.text == "Yes") { - medRequired.value = true; - } else { - medRequired.value = false; - } - } - - Widget displayForm(double width) { + Widget displayForm( + PatientManagerProvider patientManagerProvider, double width) { return SingleChildScrollView( child: Padding( padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.2) - : EdgeInsets.symmetric(horizontal: width * 0.075), + ? EdgeInsets.symmetric(horizontal: width * 0.05) + : const EdgeInsets.symmetric(horizontal: 0), child: Column( children: [ MihForm( @@ -485,7 +424,7 @@ class _AddPatientState extends State { child: MihButton( onPressed: () { if (_formKey.currentState!.validate()) { - submitForm(); + updatePatientApiCall(patientManagerProvider); } else { MihAlertServices().formNotFilledCompletely(context); } @@ -494,7 +433,7 @@ class _AddPatientState extends State { MzansiInnovationHub.of(context)!.theme.mode == "Dark"), width: 300, child: Text( - "Add", + "Update", style: TextStyle( color: MihColors.getPrimaryColor( MzansiInnovationHub.of(context)!.theme.mode == @@ -514,60 +453,12 @@ class _AddPatientState extends State { ); } - void submitForm() { - addPatientService(); - } - - MIHAction getActionButton() { - return MIHAction( - icon: const Icon(Icons.arrow_back), - iconSize: 35, - onTap: () { - context.goNamed( - 'mihHome', - extra: true, - ); - FocusScope.of(context).unfocus(); - }, - ); - } - - MIHHeader getHeader() { - return const MIHHeader( - headerAlignment: MainAxisAlignment.center, - headerItems: [ - Text( - "Set Up Patient Profile", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 25, - ), - ), - ], - ); - } - - MIHBody getBody(double width) { - return MIHBody( - borderOn: false, - bodyItems: [ - KeyboardListener( - focusNode: _focusNode, - autofocus: true, - onKeyEvent: (event) async { - if (event is KeyDownEvent && - event.logicalKey == LogicalKeyboardKey.enter) { - if (_formKey.currentState!.validate()) { - submitForm(); - } else { - MihAlertServices().formNotFilledCompletely(context); - } - } - }, - child: displayForm(width), - ), - ], - ); + void isRequired() { + if (medAidController.text == "Yes") { + medRequired.value = true; + } else if (medAidController.text == "No") { + medRequired.value = false; + } else {} } @override @@ -583,9 +474,9 @@ class _AddPatientState extends State { addressController.dispose(); medAidController.dispose(); medAidCodeController.removeListener(isRequired); - medRequired.dispose(); medMainMemController.dispose(); medAidCodeController.dispose(); + medRequired.dispose(); _focusNode.dispose(); super.dispose(); } @@ -593,67 +484,76 @@ class _AddPatientState extends State { @override void initState() { medAidController.addListener(isRequired); + PatientManagerProvider patientManagerProvider = + context.read(); setState(() { - fnameController.text = widget.signedInUser.fname; - lnameController.text = widget.signedInUser.lname; - emailController.text = widget.signedInUser.email; - medAidPosition = false; - medMainMemberPosition = false; - medAidController.text = "No"; - medMainMemController.text = "No"; + idController.text = patientManagerProvider.selectedPatient!.id_no; + fnameController.text = patientManagerProvider.selectedPatient!.first_name; + lnameController.text = patientManagerProvider.selectedPatient!.last_name; + cellController.text = patientManagerProvider.selectedPatient!.cell_no; + emailController.text = patientManagerProvider.selectedPatient!.email; + medNameController.text = + patientManagerProvider.selectedPatient!.medical_aid_name; + medNoController.text = + patientManagerProvider.selectedPatient!.medical_aid_no; + medSchemeController.text = + patientManagerProvider.selectedPatient!.medical_aid_scheme; + addressController.text = patientManagerProvider.selectedPatient!.address; + medAidController.text = + patientManagerProvider.selectedPatient!.medical_aid; + medMainMemController.text = + patientManagerProvider.selectedPatient!.medical_aid_main_member; + medAidCodeController.text = + patientManagerProvider.selectedPatient!.medical_aid_code; }); + if (medAidController.text == "Yes") { + medAidPosition = true; + } else { + medAidPosition = false; + medAidController.text = "No"; + } + if (medMainMemController.text == "Yes") { + medMainMemberPosition = true; + } else { + medMainMemberPosition = false; + medMainMemController.text = "No"; + } super.initState(); } @override Widget build(BuildContext context) { - double screenWidth = MediaQuery.of(context).size.width; - return MIHLayoutBuilder( - actionButton: getActionButton(), - header: getHeader(), - secondaryActionButton: null, - body: getBody(screenWidth), - actionDrawer: null, - secondaryActionDrawer: null, - bottomNavBar: null, - pullDownToRefresh: false, - onPullDown: () async {}, + var size = MediaQuery.of(context).size; + return MihPackageWindow( + fullscreen: false, + windowTitle: "Edit Patient Details", + onWindowTapClose: () { + context.pop(); + }, + windowBody: getBody(size.width), + ); + } + + Widget getBody(double width) { + return Consumer( + builder: (BuildContext context, + PatientManagerProvider patientManagerProvider, Widget? child) { + return KeyboardListener( + focusNode: _focusNode, + autofocus: true, + onKeyEvent: (event) async { + if (event is KeyDownEvent && + event.logicalKey == LogicalKeyboardKey.enter) { + if (_formKey.currentState!.validate()) { + updatePatientApiCall(patientManagerProvider); + } else { + MihAlertServices().formNotFilledCompletely(context); + } + } + }, + child: displayForm(patientManagerProvider, width), + ); + }, ); - // return Scaffold( - // // appBar: const MIHAppBar( - // // barTitle: "Add Patient", - // // propicFile: null, - // // ), - // //drawer: MIHAppDrawer(signedInUser: widget.signedInUser), - // body: SafeArea( - // child: Stack( - // children: [ - // KeyboardListener( - // focusNode: _focusNode, - // autofocus: true, - // onKeyEvent: (event) async { - // if (event is KeyDownEvent && - // event.logicalKey == LogicalKeyboardKey.enter) { - // submitForm(); - // } - // }, - // child: displayForm(), - // ), - // Positioned( - // top: 10, - // left: 5, - // width: 50, - // height: 50, - // child: IconButton( - // onPressed: () { - // Navigator.of(context).pop(); - // }, - // icon: const Icon(Icons.arrow_back), - // ), - // ) - // ], - // ), - // ), - // ); } } diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/components/prescip_input.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/components/prescip_input.dart similarity index 99% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/components/prescip_input.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/components/prescip_input.dart index 6c6e90b2..543d26a7 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/components/prescip_input.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/components/prescip_input.dart @@ -6,7 +6,7 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_numeric_stepper.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/components/medicine_search.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/components/medicine_search.dart'; 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'; diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_claim_statement_files_list.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_claim_statement_files_list.dart similarity index 60% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_claim_statement_files_list.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_claim_statement_files_list.dart index 469018c5..30bec822 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_claim_statement_files_list.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_claim_statement_files_list.dart @@ -5,44 +5,26 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_claim_statement_generation_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart'; 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_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/claim_statement_file.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/list_builders/build_file_view.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_file_view.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:supertokens_flutter/http.dart' as http; import 'package:http/http.dart' as http2; import "package:universal_html/html.dart" as html; class BuildClaimStatementFileList extends StatefulWidget { - final AppUser signedInUser; - final List files; - final Patient selectedPatient; - final Business? business; - final BusinessUser? businessUser; - final String type; - final String env; const BuildClaimStatementFileList({ super.key, - required this.files, - required this.signedInUser, - required this.selectedPatient, - required this.business, - required this.businessUser, - required this.type, - required this.env, }); @override @@ -91,32 +73,32 @@ class _BuildClaimStatementFileListState ); } - void deleteFilePopUp(String filePath, int fileID) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => MIHDeleteMessage( - deleteType: "File", - onTap: () async { - //API Call here - await MIHClaimStatementGenerationApi - .deleteClaimStatementFilesByFileID( - PatientViewArguments( - widget.signedInUser, - widget.selectedPatient, - widget.businessUser, - widget.business, - "business", - ), - widget.env, - filePath, - fileID, - context, - ); - }, - ), - ); - } + // void deleteFilePopUp(String filePath, int fileID) { + // showDialog( + // context: context, + // barrierDismissible: false, + // builder: (context) => MIHDeleteMessage( + // deleteType: "File", + // onTap: () async { + // //API Call here + // await MIHClaimStatementGenerationApi + // .deleteClaimStatementFilesByFileID( + // PatientViewArguments( + // widget.signedInUser, + // widget.selectedPatient, + // widget.businessUser, + // widget.business, + // "business", + // ), + // widget.env, + // filePath, + // fileID, + // context, + // ); + // }, + // ), + // ); + // } String getFileName(String path) { //print(pdfLink.split(".")[1]); @@ -159,9 +141,10 @@ class _BuildClaimStatementFileListState } } - void viewFilePopUp(String fileName, String filePath, int fileID, String url) { + void viewFilePopUp(PatientManagerProvider patientManagerProvider, + String fileName, String filePath, int fileID, String url) { bool hasAccessToDelete = false; - if (widget.type == "business") { + if (!patientManagerProvider.personalMode) { hasAccessToDelete = true; } @@ -263,7 +246,7 @@ class _BuildClaimStatementFileListState backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - deleteFilePopUp(filePath, fileID); + // deleteFilePopUp(filePath, fileID); }, ), ); @@ -332,135 +315,149 @@ class _BuildClaimStatementFileListState @override Widget build(BuildContext context) { - if (widget.files.isNotEmpty) { - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - separatorBuilder: (BuildContext context, int index) { - return Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - }, - itemCount: widget.files.length, - itemBuilder: (context, index) { - return ListTile( - title: Text( - widget.files[index].file_name, - style: TextStyle( + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + if (patientManagerProvider.patientClaimsDocuments!.isNotEmpty) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, int index) { + return Divider( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - subtitle: Text( - widget.files[index].insert_date, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - // trailing: Icon( - // Icons.arrow_forward, - // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - onTap: () async { - await getFileUrlApiCall(widget.files[index].file_path) - .then((urlHere) { - //print(url); - setState(() { - fileUrl = urlHere; - }); - }); - - viewFilePopUp( - widget.files[index].file_name, - widget.files[index].file_path, - widget.files[index].idclaim_statement_file, - fileUrl); + ); }, - ); - }, - ); - } else { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - children: [ - const SizedBox(height: 50), - Stack( - alignment: AlignmentDirectional.center, - children: [ - Icon( - MihIcons.mihRing, - size: 165, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - Icon( - Icons.file_open_outlined, - size: 110, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ], - ), - const SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Text( - "No Claims or Statements have been added to this profile.", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), + itemCount: patientManagerProvider.patientClaimsDocuments!.length, + itemBuilder: (context, index) { + return ListTile( + title: Text( + patientManagerProvider + .patientClaimsDocuments![index].file_name, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), ), - ], - ), - const SizedBox(height: 25), - Visibility( - visible: widget.business != null, - child: Center( - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.normal, + subtitle: Text( + patientManagerProvider + .patientClaimsDocuments![index].insert_date, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + // trailing: Icon( + // Icons.arrow_forward, + // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + onTap: () async { + await getFileUrlApiCall(patientManagerProvider + .patientClaimsDocuments![index].file_path) + .then((urlHere) { + //print(url); + setState(() { + fileUrl = urlHere; + }); + }); + + viewFilePopUp( + patientManagerProvider, + patientManagerProvider + .patientClaimsDocuments![index].file_name, + patientManagerProvider + .patientClaimsDocuments![index].file_path, + patientManagerProvider.patientClaimsDocuments![index] + .idclaim_statement_file, + fileUrl); + }, + ); + }, + ); + } else { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + const SizedBox(height: 50), + Stack( + alignment: AlignmentDirectional.center, + children: [ + Icon( + MihIcons.mihRing, + size: 165, color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), - children: [ - TextSpan(text: "Press "), - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Icon( - Icons.menu, - size: 20, + Icon( + Icons.file_open_outlined, + size: 110, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ], + ), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Text( + "No Claims or Statements have been added to this profile.", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), ), - TextSpan(text: " to generate the first document"), - ], + ), + ], + ), + const SizedBox(height: 25), + Visibility( + visible: !patientManagerProvider.personalMode, + child: Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.normal, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + children: [ + TextSpan(text: "Press "), + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Icon( + Icons.menu, + size: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + TextSpan(text: " to generate the first document"), + ], + ), + ), ), ), - ), + ], ), - ], - ), - ); - } + ); + } + }, + ); } } diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_file_view.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_file_view.dart similarity index 100% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_file_view.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_file_view.dart diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_files_list.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_files_list.dart similarity index 52% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_files_list.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_files_list.dart index 3a302712..a7b38555 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_files_list.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_files_list.dart @@ -1,48 +1,30 @@ import 'dart:async'; -import 'dart:convert'; import 'package:fl_downloader/fl_downloader.dart'; import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart'; 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_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/files.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/list_builders/build_file_view.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_file_view.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:supertokens_flutter/http.dart' as http; import 'package:http/http.dart' as http2; import "package:universal_html/html.dart" as html; class BuildFilesList extends StatefulWidget { - final AppUser signedInUser; - final List files; - final Patient selectedPatient; - final Business? business; - final BusinessUser? businessUser; - final String type; - final String env; const BuildFilesList({ super.key, - required this.files, - required this.signedInUser, - required this.selectedPatient, - required this.business, - required this.businessUser, - required this.type, - required this.env, }); @override @@ -68,71 +50,72 @@ class _BuildFilesListState extends State { return teporaryFileUrl; } - Future deleteFileApiCall(String filePath, int fileID) async { - var response = await MihFileApi.deleteFile( - widget.selectedPatient.app_id, - widget.env, - "patient_files", - filePath.split("/").last, - context, - ); - if (response == 200) { - // delete file from database - await deletePatientFileLocationToDB(fileID); - } else { - String message = - "The File has not been deleted successfully. Please try again."; - successPopUp(message); - } - } + // Future deleteFileApiCall(PatientManagerProvider patientManagerProvider, + // String filePath, int fileID) async { + // var response = await MihFileApi.deleteFile( + // patientManagerProvider.selectedPatient!.app_id, + // widget.env, + // "patient_files", + // filePath.split("/").last, + // context, + // ); + // if (response == 200) { + // // delete file from database + // await deletePatientFileLocationToDB(fileID); + // } else { + // String message = + // "The File has not been deleted successfully. Please try again."; + // successPopUp(message); + // } + // } - Future deletePatientFileLocationToDB(int fileID) async { - showDialog( - context: context, - builder: (context) { - return const Mihloadingcircle(); - }, - ); - var response2 = await http.delete( - Uri.parse("$baseAPI/patient_files/delete/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "idpatient_files": fileID, - "env": widget.env, - }), - ); - if (response2.statusCode == 200) { - context.pop(); //Remove Loading Dialog - context.pop(); //Remove Delete Dialog - context.pop(); //Remove File View Dialog - context.pop(); //Remove File List Dialog - //print(widget.business); - if (widget.business == null) { - context.pushNamed('patientManagerPatient', - extra: PatientViewArguments( - widget.signedInUser, - widget.selectedPatient, - widget.businessUser, - widget.business, - "personal")); - } else { - context.pushNamed('patientManagerPatient', - extra: PatientViewArguments( - widget.signedInUser, - widget.selectedPatient, - widget.businessUser, - widget.business, - "business")); - } - String message = - "The File has been deleted successfully. This means it will no longer be visible on your and cannot be used for future appointments."; - successPopUp(message); - } else { - internetConnectionPopUp(); - } - } + // Future deletePatientFileLocationToDB(int fileID) async { + // showDialog( + // context: context, + // builder: (context) { + // return const Mihloadingcircle(); + // }, + // ); + // var response2 = await http.delete( + // Uri.parse("$baseAPI/patient_files/delete/"), + // headers: { + // "Content-Type": "application/json; charset=UTF-8" + // }, + // body: jsonEncode({ + // "idpatient_files": fileID, + // "env": widget.env, + // }), + // ); + // if (response2.statusCode == 200) { + // context.pop(); //Remove Loading Dialog + // context.pop(); //Remove Delete Dialog + // context.pop(); //Remove File View Dialog + // context.pop(); //Remove File List Dialog + // //print(widget.business); + // if (widget.business == null) { + // context.pushNamed('patientManagerPatient', + // extra: PatientViewArguments( + // widget.signedInUser, + // widget.selectedPatient, + // widget.businessUser, + // widget.business, + // "personal")); + // } else { + // context.pushNamed('patientManagerPatient', + // extra: PatientViewArguments( + // widget.signedInUser, + // widget.selectedPatient, + // widget.businessUser, + // widget.business, + // "business")); + // } + // String message = + // "The File has been deleted successfully. This means it will no longer be visible on your and cannot be used for future appointments."; + // successPopUp(message); + // } else { + // internetConnectionPopUp(); + // } + // } void internetConnectionPopUp() { showDialog( @@ -155,18 +138,18 @@ class _BuildFilesListState extends State { ); } - void deleteFilePopUp(String filePath, int fileID) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => MIHDeleteMessage( - deleteType: "File", - onTap: () async { - await deleteFileApiCall(filePath, fileID); - }, - ), - ); - } + // void deleteFilePopUp(String filePath, int fileID) { + // showDialog( + // context: context, + // barrierDismissible: false, + // builder: (context) => MIHDeleteMessage( + // deleteType: "File", + // onTap: () async { + // await deleteFileApiCall(filePath, fileID); + // }, + // ), + // ); + // } String getFileName(String path) { //print(pdfLink.split(".")[1]); @@ -202,9 +185,10 @@ class _BuildFilesListState extends State { } } - void viewFilePopUp(String fileName, String filePath, int fileID, String url) { + void viewFilePopUp(PatientManagerProvider patientManagerProvider, + String fileName, String filePath, int fileID, String url) { bool hasAccessToDelete = false; - if (widget.type == "business") { + if (!patientManagerProvider.personalMode) { hasAccessToDelete = true; } @@ -307,7 +291,7 @@ class _BuildFilesListState extends State { backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - deleteFilePopUp(filePath, fileID); + // deleteFilePopUp(filePath, fileID); }, ), ); @@ -368,133 +352,138 @@ class _BuildFilesListState extends State { @override Widget build(BuildContext context) { - if (widget.files.isNotEmpty) { - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - separatorBuilder: (BuildContext context, int index) { - return Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - }, - itemCount: widget.files.length, - itemBuilder: (context, index) { - return ListTile( - title: Text( - widget.files[index].file_name, - style: TextStyle( + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + if (patientManagerProvider.patientDocuments!.isNotEmpty) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, int index) { + return Divider( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - subtitle: Text( - widget.files[index].insert_date, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - // trailing: Icon( - // Icons.arrow_forward, - // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - onTap: () async { - await getFileUrlApiCall(widget.files[index].file_path) - .then((urlHere) { - //print(url); - setState(() { - fileUrl = urlHere; - }); - }); - - viewFilePopUp( - widget.files[index].file_name, - widget.files[index].file_path, - widget.files[index].idpatient_files, - fileUrl); + ); }, - ); - }, - ); - } else { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Column( - // mainAxisAlignment: MainAxisAlignment.center, - // crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 50), - Stack( - alignment: AlignmentDirectional.center, - children: [ - Icon( - MihIcons.mihRing, - size: 165, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - Icon( - Icons.file_present, - size: 110, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ], - ), - const SizedBox(height: 10), - Text( - "No Documents have been added to this profile.", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - const SizedBox(height: 25), - Center( - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( + itemCount: patientManagerProvider.patientDocuments!.length, + itemBuilder: (context, index) { + return ListTile( + title: Text( + patientManagerProvider.patientDocuments![index].file_name, style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.normal, color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), + ), + subtitle: Text( + patientManagerProvider.patientDocuments![index].insert_date, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + // trailing: Icon( + // Icons.arrow_forward, + // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + onTap: () async { + await getFileUrlApiCall(patientManagerProvider + .patientDocuments![index].file_path) + .then((urlHere) { + //print(url); + setState(() { + fileUrl = urlHere; + }); + }); + + viewFilePopUp( + patientManagerProvider, + patientManagerProvider.patientDocuments![index].file_name, + patientManagerProvider.patientDocuments![index].file_path, + patientManagerProvider + .patientDocuments![index].idpatient_files, + fileUrl); + }, + ); + }, + ); + } else { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Column( + // mainAxisAlignment: MainAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 50), + Stack( + alignment: AlignmentDirectional.center, children: [ - TextSpan(text: "Press "), - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Icon( - Icons.menu, - size: 20, + Icon( + MihIcons.mihRing, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + Icon( + Icons.file_present, + size: 110, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ], + ), + const SizedBox(height: 10), + Text( + "No Documents have been added to this profile.", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + const SizedBox(height: 25), + Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.normal, color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), + children: [ + TextSpan(text: "Press "), + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Icon( + Icons.menu, + size: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + TextSpan(text: " to add "), + !patientManagerProvider.personalMode + ? TextSpan( + text: " or generate a the first document") + : TextSpan(text: " the first document"), + ], ), - TextSpan(text: " to add "), - widget.business != null - ? TextSpan(text: " or generate a the first document") - : TextSpan(text: " the first document"), - ], + ), ), - ), + ], ), - ], - ), - ); - // return const Center( - // child: Text( - // "No Documents Available", - // style: TextStyle(fontSize: 25, color: Colors.grey), - // textAlign: TextAlign.center, - // ), - // ); - } + ); + } + }, + ); } } diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_icd10_code_list.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_icd10_code_list.dart similarity index 100% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_icd10_code_list.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_icd10_code_list.dart diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_med_list.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_med_list.dart similarity index 100% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_med_list.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_med_list.dart diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_notes_list.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_notes_list.dart similarity index 52% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_notes_list.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_notes_list.dart index e3bb088a..832d0d9f 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/list_builders/build_notes_list.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/list_builders/build_notes_list.dart @@ -1,38 +1,25 @@ -import 'dart:convert'; import 'package:flutter_speed_dial/flutter_speed_dial.dart'; +import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart'; 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_success_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/notes.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; import 'package:flutter/material.dart'; -import 'package:supertokens_flutter/http.dart' as http; +import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; +import 'package:provider/provider.dart'; class BuildNotesList extends StatefulWidget { - final AppUser signedInUser; - final List notes; - final Patient selectedPatient; - final Business? business; - final BusinessUser? businessUser; - final String type; const BuildNotesList({ super.key, - required this.notes, - required this.signedInUser, - required this.selectedPatient, - required this.business, - required this.businessUser, - required this.type, }); @override @@ -48,45 +35,80 @@ class _BuildNotesListState extends State { int indexOn = 0; final baseAPI = AppEnviroment.baseApiUrl; - Future deleteNoteApiCall(int NoteId) async { - var response = await http.delete( - Uri.parse("$baseAPI/notes/delete/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({"idpatient_notes": NoteId}), - ); + Future deleteNoteApiCall( + PatientManagerProvider patientManagerProvider, int NoteId) async { + int statusCode = await MihPatientServices() + .deletePatientConsultaionNote(NoteId, patientManagerProvider); //print("Here4"); //print(response.statusCode); - if (response.statusCode == 200) { - Navigator.of(context).pop(); - Navigator.of(context).pop(); - if (widget.business == null) { - Navigator.of(context).pushNamed('/patient-manager/patient', - arguments: PatientViewArguments( - widget.signedInUser, - widget.selectedPatient, - widget.businessUser, - widget.business, - "personal")); - } else { - Navigator.of(context).pushNamed('/patient-manager/patient', - arguments: PatientViewArguments( - widget.signedInUser, - widget.selectedPatient, - widget.businessUser, - widget.business, - "business")); - } - setState(() {}); + if (statusCode == 200) { 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); + successPopUp("Successfuly Deleted", message); } else { internetConnectionPopUp(); } } + void successPopUp(String title, String message) { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.check_circle_outline_rounded, + size: 150, + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: title, + alertBody: Column( + children: [ + Text( + message, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + context.pop(); + context.pop(); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Dismiss", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + // return MIHSuccessMessage( + // successType: "Success", + // successMessage: message, + // ); + }, + ); + } + void internetConnectionPopUp() { showDialog( context: context, @@ -96,32 +118,22 @@ class _BuildNotesListState extends State { ); } - void successPopUp(String message) { - showDialog( - context: context, - builder: (context) { - return MIHSuccessMessage( - successType: "Success", - successMessage: message, - ); - }, - ); - } - - void deletePatientPopUp(int NoteId) { + void deletePatientPopUp( + PatientManagerProvider patientManagerProvider, int NoteId) { showDialog( context: context, barrierDismissible: false, builder: (context) => MIHDeleteMessage( deleteType: "Note", onTap: () { - deleteNoteApiCall(NoteId); + deleteNoteApiCall(patientManagerProvider, NoteId); }, ), ); } - void viewNotePopUp(Note selectednote) { + void viewNotePopUp(MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Note selectednote) { setState(() { noteTitleController.text = selectednote.note_name; noteTextController.text = selectednote.note_text; @@ -130,8 +142,8 @@ class _BuildNotesListState extends State { dateController.text = selectednote.insert_date; }); bool hasAccessToDelete = false; - if (widget.type == "business" && - selectednote.doc_office == widget.business!.Name) { + if (!patientManagerProvider.personalMode && + selectednote.doc_office == profileProvider.business!.Name) { hasAccessToDelete = true; } showDialog( @@ -159,7 +171,8 @@ class _BuildNotesListState extends State { backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - deletePatientPopUp(selectednote.idpatient_notes); + deletePatientPopUp( + patientManagerProvider, selectednote.idpatient_notes); }, ), ] @@ -248,136 +261,141 @@ class _BuildNotesListState extends State { @override Widget build(BuildContext context) { - if (widget.notes.isNotEmpty) { - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - separatorBuilder: (BuildContext context, int index) { - return Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - }, - itemCount: widget.notes.length, - itemBuilder: (context, index) { - String notePreview = widget.notes[index].note_text; - if (notePreview.length > 30) { - notePreview = "${notePreview.substring(0, 30)} ..."; - } - return ListTile( - title: Text( - "${widget.notes[index].note_name}\n${widget.notes[index].doc_office} - ${widget.notes[index].doctor}", - style: TextStyle( + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + if (patientManagerProvider.consultationNotes!.isNotEmpty) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, int index) { + return Divider( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - subtitle: Text( - "${widget.notes[index].insert_date}:\n$notePreview", - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), //Text(widget.notes[index].note_text), - trailing: Icon( - Icons.arrow_forward, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - onTap: () { - viewNotePopUp(widget.notes[index]); + ); }, - ); - }, - ); - } else { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - children: [ - const SizedBox(height: 50), - Stack( - alignment: AlignmentDirectional.center, - children: [ - Icon( - MihIcons.mihRing, - size: 165, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - Icon( - Icons.article_outlined, - size: 110, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ], - ), - const SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Text( - "No Notes have been added to this profile.", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), + itemCount: patientManagerProvider.consultationNotes!.length, + itemBuilder: (context, index) { + String notePreview = + patientManagerProvider.consultationNotes![index].note_text; + if (notePreview.length > 30) { + notePreview = "${notePreview.substring(0, 30)} ..."; + } + return ListTile( + title: Text( + "${patientManagerProvider.consultationNotes![index].note_name}\n${patientManagerProvider.consultationNotes![index].doc_office} - ${patientManagerProvider.consultationNotes![index].doctor}", + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), ), - ], - ), - const SizedBox(height: 25), - Visibility( - visible: widget.business != null, - child: Center( - child: RichText( - textAlign: TextAlign.center, - text: TextSpan( - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.normal, + subtitle: Text( + "${patientManagerProvider.consultationNotes![index].insert_date}:\n$notePreview", + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), //Text(widget.notes[index].note_text), + trailing: Icon( + Icons.arrow_forward, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + onTap: () { + viewNotePopUp( + profileProvider, + patientManagerProvider, + patientManagerProvider.consultationNotes![index], + ); + }, + ); + }, + ); + } else { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + const SizedBox(height: 50), + Stack( + alignment: AlignmentDirectional.center, + children: [ + Icon( + MihIcons.mihRing, + size: 165, color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), - children: [ - TextSpan(text: "Press "), - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Icon( - Icons.menu, - size: 20, + Icon( + Icons.article_outlined, + size: 110, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ], + ), + const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Text( + "No Notes have been added to this profile.", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), ), - TextSpan(text: " to add the first note"), - ], + ), + ], + ), + const SizedBox(height: 25), + Visibility( + visible: !patientManagerProvider.personalMode, + child: Center( + child: RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.normal, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + children: [ + TextSpan(text: "Press "), + WidgetSpan( + alignment: PlaceholderAlignment.middle, + child: Icon( + Icons.menu, + size: 20, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + TextSpan(text: " to add the first note"), + ], + ), + ), ), ), - ), + ], ), - ], - ), - ); - // return const Center( - // child: Text( - // "No Notes Available", - // style: TextStyle(fontSize: 25, color: Colors.grey), - // textAlign: TextAlign.center, - // ), - // ); - } + ); + } + }, + ); } } diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/package_tiles/patient_profile_tile.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tiles/patient_profile_tile.dart similarity index 85% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/package_tiles/patient_profile_tile.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/package_tiles/patient_profile_tile.dart index e6a82763..1fe19f93 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/package_tiles/patient_profile_tile.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tiles/patient_profile_tile.dart @@ -4,7 +4,9 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:provider/provider.dart'; class PatientProfileTile extends StatefulWidget { final PatientViewArguments arguments; @@ -26,9 +28,11 @@ class _PatientProfileTileState extends State { return MihPackageTile( authenticateUser: true, onTap: () { + PatientManagerProvider patientManagerProvider = + context.read(); + patientManagerProvider.setPersonalMode(true); context.goNamed( 'patientProfile', - extra: widget.arguments, ); // Navigator.of(context).pushNamed( // '/patient-profile', diff --git a/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_claim_or_statement.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_claim_or_statement.dart new file mode 100644 index 00000000..3932042b --- /dev/null +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_claim_or_statement.dart @@ -0,0 +1,99 @@ +import 'package:flutter_speed_dial/flutter_speed_dial.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/components/claim_statement_window.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_claim_statement_files_list.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class PatientClaimOrStatement extends StatefulWidget { + const PatientClaimOrStatement({ + super.key, + }); + + @override + State createState() => + _PatientClaimOrStatementState(); +} + +class _PatientClaimOrStatementState extends State { + void claimOrStatementWindow() { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => ClaimStatementWindow(), + ); + } + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return MihPackageToolBody( + borderOn: false, + bodyItem: getBody(), + ); + } + + Widget getBody() { + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + return Stack( + children: [ + Column( + children: [ + //const Placeholder(), + BuildClaimStatementFileList(), + ], + ), + Visibility( + visible: patientManagerProvider.personalMode, + child: Positioned( + right: 10, + bottom: 10, + child: MihFloatingMenu( + icon: Icons.file_copy, + animatedIcon: AnimatedIcons.menu_close, + children: [ + SpeedDialChild( + child: Icon( + Icons.add, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + label: "Generate Claim/ Statement", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onTap: () { + claimOrStatementWindow(); + }, + ) + ], + ), + ), + ), + ], + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_consultation.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_consultation.dart similarity index 65% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_consultation.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_consultation.dart index a6489ac9..fdd28fbe 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_consultation.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_consultation.dart @@ -1,6 +1,7 @@ -import 'dart:convert'; import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; @@ -12,33 +13,15 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; 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_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/notes.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/list_builders/build_notes_list.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_notes_list.dart'; import 'package:flutter/material.dart'; -import 'package:supertokens_flutter/http.dart' as http; +import 'package:provider/provider.dart'; class PatientConsultation extends StatefulWidget { - final String patientAppId; - final Patient selectedPatient; - final AppUser signedInUser; - final Business? business; - final BusinessUser? businessUser; - final String type; const PatientConsultation({ super.key, - required this.patientAppId, - required this.selectedPatient, - required this.signedInUser, - required this.business, - required this.businessUser, - required this.type, }); @override @@ -46,7 +29,6 @@ class PatientConsultation extends StatefulWidget { } class _PatientConsultationState extends State { - late Future> futueNotes; final titleController = TextEditingController(); final noteTextController = TextEditingController(); final officeController = TextEditingController(); @@ -56,33 +38,18 @@ class _PatientConsultationState extends State { String endpoint = "${AppEnviroment.baseApiUrl}/notes/patients/"; final _formKey = GlobalKey(); - Future> fetchNotes(String endpoint) async { - final response = await http.get(Uri.parse( - "${AppEnviroment.baseApiUrl}/notes/patients/${widget.selectedPatient.app_id}")); - if (response.statusCode == 200) { - Iterable l = jsonDecode(response.body); - List notes = - List.from(l.map((model) => Note.fromJson(model))); - //print("Here notes"); - return notes; - } else { - internetConnectionPopUp(); - throw Exception('failed to load patients'); - } - } - - void addNotePopUp(double width) { + void addNotePopUp(MzansiProfileProvider profileProvider, double width) { DateTime now = new DateTime.now(); DateTime date = new DateTime(now.year, now.month, now.day); var title = ""; - print("Business User: ${widget.businessUser}"); - if (widget.businessUser?.title == "Doctor") { + print("Business User: ${profileProvider.businessUser}"); + if (profileProvider.businessUser?.title == "Doctor") { title = "Dr."; } setState(() { - officeController.text = widget.business!.Name; + officeController.text = profileProvider.business!.Name; doctorController.text = - "$title ${widget.signedInUser.fname} ${widget.signedInUser.lname}"; + "$title ${profileProvider.user!.fname} ${profileProvider.user!.lname}"; dateController.text = date.toString().substring(0, 10); }); showDialog( @@ -205,7 +172,7 @@ class _PatientConsultationState extends State { child: MihButton( onPressed: () { if (_formKey.currentState!.validate()) { - addPatientNoteAPICall(); + // addPatientNoteAPICall(); Navigator.pop(context); } else { MihAlertServices().formNotFilledCompletely(context); @@ -236,38 +203,6 @@ class _PatientConsultationState extends State { ); } - Future addPatientNoteAPICall() async { - // String title = ""; - // if (widget.businessUser!.title == "Doctor") { - // title = "Dr."; - // } - var response = await http.post( - Uri.parse("${AppEnviroment.baseApiUrl}/notes/insert/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "note_name": titleController.text, - "note_text": noteTextController.text, - "doc_office": officeController.text, - "doctor": doctorController.text, - "app_id": widget.selectedPatient.app_id, - }), - ); - if (response.statusCode == 201) { - setState(() { - futueNotes = fetchNotes(endpoint + widget.patientAppId.toString()); - }); - // Navigator.of(context) - // .pushNamed('/patient-manager', arguments: widget.userEmail); - String message = - "Your note has been successfully added to the patients medical record. You can now view it alongside their other important information."; - successPopUp(message); - } else { - internetConnectionPopUp(); - } - } - bool isFieldsFilled() { if (titleController.text.isEmpty || noteTextController.text.isEmpty || @@ -321,7 +256,6 @@ class _PatientConsultationState extends State { @override void initState() { - futueNotes = fetchNotes(endpoint + widget.patientAppId); noteTextController.addListener(() { setState(() { _counter.value = noteTextController.text.characters.length; @@ -340,71 +274,56 @@ class _PatientConsultationState extends State { } Widget getBody(double width) { - return Stack( - children: [ - MihSingleChildScroll( - child: FutureBuilder( - future: futueNotes, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center( - child: Mihloadingcircle(), - ); - } else if (snapshot.hasData) { - final notesList = snapshot.data!; - return Column(children: [ - BuildNotesList( - notes: notesList, - signedInUser: widget.signedInUser, - selectedPatient: widget.selectedPatient, - business: widget.business, - businessUser: widget.businessUser, - type: widget.type, - ), - ]); - } else { - return const Center( - child: Text("Error Loading Notes"), - ); - } - }, - ), - ), - Visibility( - visible: widget.type != "personal", - child: Positioned( - right: 10, - bottom: 10, - child: MihFloatingMenu( - icon: Icons.add, - animatedIcon: AnimatedIcons.menu_close, - children: [ - SpeedDialChild( - child: Icon( - Icons.add, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - label: "Add Note", - labelBackgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - labelStyle: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontWeight: FontWeight.bold, - ), - backgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onTap: () { - // addConsultationNotePopUp(); - addNotePopUp(width); - }, - ) - ], + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + return Stack( + children: [ + MihSingleChildScroll( + child: Column(children: [ + BuildNotesList(), + ])), + Visibility( + visible: !patientManagerProvider.personalMode, + child: Positioned( + right: 10, + bottom: 10, + child: MihFloatingMenu( + icon: Icons.add, + animatedIcon: AnimatedIcons.menu_close, + children: [ + SpeedDialChild( + child: Icon( + Icons.add, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + label: "Add Note", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onTap: () { + // addConsultationNotePopUp(); + addNotePopUp(profileProvider, width); + }, + ) + ], + ), + ), ), - ), - ), - ], + ], + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_documents.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_documents.dart similarity index 70% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_documents.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_documents.dart index 44a2e485..7f278050 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_documents.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_documents.dart @@ -1,10 +1,13 @@ -import 'dart:convert'; - import 'package:flutter_speed_dial/flutter_speed_dial.dart'; +import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; @@ -16,34 +19,16 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; 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_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/files.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/components/prescip_input.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/list_builders/build_files_list.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/components/prescip_input.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/list_builders/build_files_list.dart'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; -import 'package:supertokens_flutter/http.dart' as http; +import 'package:provider/provider.dart'; class PatientDocuments extends StatefulWidget { - final int patientIndex; - final Patient selectedPatient; - final AppUser signedInUser; - final Business? business; - final BusinessUser? businessUser; - final String type; const PatientDocuments({ super.key, - required this.patientIndex, - required this.selectedPatient, - required this.signedInUser, - required this.business, - required this.businessUser, - required this.type, }); @override @@ -51,7 +36,6 @@ class PatientDocuments extends StatefulWidget { } class _PatientDocumentsState extends State { - late Future> futueFiles; final selectedFileController = TextEditingController(); final startDateController = TextEditingController(); final endDateTextController = TextEditingController(); @@ -68,9 +52,10 @@ class _PatientDocumentsState extends State { final _formKey2 = GlobalKey(); late String env; - Future submitDocUploadForm() async { + Future submitDocUploadForm( + PatientManagerProvider patientManagerProvider) async { if (isFileFieldsFilled()) { - await uploadSelectedFile(selected); + await uploadSelectedFile(patientManagerProvider, selected); } else { showDialog( context: context, @@ -81,75 +66,49 @@ class _PatientDocumentsState extends State { } } - Future> fetchFiles() async { - final response = await http.get(Uri.parse( - "${AppEnviroment.baseApiUrl}/patient_files/get/${widget.selectedPatient.app_id}")); - //print(response.statusCode); - //print(response.body); - if (response.statusCode == 200) { - Iterable l = jsonDecode(response.body); - List files = - List.from(l.map((model) => PFile.fromJson(model))); - return files; - } else { - internetConnectionPopUp(); - throw Exception('failed to load patients'); - } - } - - Future addPatientFileLocationToDB(PlatformFile? file) async { + Future addPatientFileLocationToDB( + PatientManagerProvider patientManagerProvider, PlatformFile? file) async { showDialog( context: context, builder: (context) { return const Mihloadingcircle(); }, ); - var fname = file!.name.replaceAll(RegExp(r' '), '-'); - var filePath = "${widget.selectedPatient.app_id}/patient_files/$fname"; - var response2 = await http.post( - Uri.parse("${AppEnviroment.baseApiUrl}/patient_files/insert/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "file_path": filePath, - "file_name": fname, - "app_id": widget.selectedPatient.app_id - }), - ); - //print("here5"); - //print(response2.statusCode); - if (response2.statusCode == 201) { + int statusCode = + await MihPatientServices().addPatientFile(file, patientManagerProvider); + if (statusCode == 201) { setState(() { selectedFileController.clear(); - futueFiles = fetchFiles(); }); + var fname = file!.name.replaceAll(RegExp(r' '), '-'); // end loading circle Navigator.of(context).pop(); String message = - "The file ${file.name.replaceAll(RegExp(r' '), '-')} has been successfully generated and added to ${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}'s record. You can now access and download it for their use."; - successPopUp(message); + "The file $fname has been successfully generated and added to ${patientManagerProvider.selectedPatient!.first_name} ${patientManagerProvider.selectedPatient!.last_name}'s record. You can now access and download it for their use."; + successPopUp("Successfully Uplouded File", message); } else { internetConnectionPopUp(); } } - Future uploadSelectedFile(PlatformFile? file) async { + Future uploadSelectedFile( + PatientManagerProvider patientManagerProvider, PlatformFile? file) async { var response = await MihFileApi.uploadFile( - widget.selectedPatient.app_id, + patientManagerProvider.selectedPatient!.app_id, env, "patient_files", file, context, ); if (response == 200) { - await addPatientFileLocationToDB(file); + await addPatientFileLocationToDB(patientManagerProvider, file); } else { internetConnectionPopUp(); } } - Future generateMedCert() async { + Future generateMedCert(MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider) async { //start loading circle showDialog( context: context, @@ -157,73 +116,30 @@ class _PatientDocumentsState extends State { return const Mihloadingcircle(); }, ); - DateTime now = DateTime.now(); - // DateTime date = new DateTime(now.year, now.month, now.day); - String fileName = - "Med-Cert-${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}-${now.toString().substring(0, 19)}.pdf" - .replaceAll(RegExp(r' '), '-'); - var response1 = await http.post( - Uri.parse("${AppEnviroment.baseApiUrl}/minio/generate/med-cert/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "app_id": widget.selectedPatient.app_id, - "env": env, - "patient_full_name": - "${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}", - "fileName": fileName, - "id_no": widget.selectedPatient.id_no, - "docfname": - "DR. ${widget.signedInUser.fname} ${widget.signedInUser.lname}", - "startDate": startDateController.text, - "busName": widget.business!.Name, - "busAddr": "*TO BE ADDED IN THE FUTURE*", - "busNo": widget.business!.contact_no, - "busEmail": widget.business!.bus_email, - "endDate": endDateTextController.text, - "returnDate": retDateTextController.text, - "logo_path": widget.business!.logo_path, - "sig_path": widget.businessUser!.sig_path, - }), + int statusCodeCetificateGeneration = + await MihPatientServices().generateMedicalCertificate( + startDateController.text, + endDateTextController.text, + retDateTextController.text, + profileProvider, + patientManagerProvider, ); - print(response1.statusCode); - if (response1.statusCode == 200) { - var response2 = await http.post( - Uri.parse("${AppEnviroment.baseApiUrl}/patient_files/insert/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "file_path": - "${widget.selectedPatient.app_id}/patient_files/$fileName", - "file_name": fileName, - "app_id": widget.selectedPatient.app_id - }), - ); - //print(response2.statusCode); - if (response2.statusCode == 201) { - setState(() { - startDateController.clear(); - endDateTextController.clear(); - retDateTextController.clear(); - futueFiles = fetchFiles(); - }); - // end loading circle - Navigator.of(context).pop(); - Navigator.of(context).pop(); - String message = - "The medical certificate $fileName has been successfully generated and added to ${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}'s record. You can now access and download it for their use."; - successPopUp(message); - } else { - internetConnectionPopUp(); - } + DateTime now = DateTime.now(); + String fileName = + "Med-Cert-${patientManagerProvider.selectedPatient!.first_name} ${patientManagerProvider.selectedPatient!.last_name}-${now.toString().substring(0, 19)}.pdf" + .replaceAll(RegExp(r' '), '-'); + if (statusCodeCetificateGeneration == 200) { + context.pop(); //Loading removal + String message = + "The medical certificate $fileName has been successfully generated and added to ${patientManagerProvider.selectedPatient!.first_name} ${patientManagerProvider.selectedPatient!.last_name}'s record. You can now access and download it for their use."; + successPopUp("Successfully Generated Certificate", message); } else { internetConnectionPopUp(); } } - void uploudFilePopUp(double width) { + void uploudFilePopUp( + PatientManagerProvider patientManagerProvider, double width) { showDialog( context: context, barrierDismissible: false, @@ -304,7 +220,7 @@ class _PatientDocumentsState extends State { child: MihButton( onPressed: () { if (_formKey.currentState!.validate()) { - submitDocUploadForm(); + submitDocUploadForm(patientManagerProvider); // uploadSelectedFile(selected); Navigator.pop(context); } else { @@ -336,7 +252,10 @@ class _PatientDocumentsState extends State { ); } - void medCertPopUp() { + void medCertPopUp( + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + ) { showDialog( context: context, barrierDismissible: false, @@ -387,7 +306,8 @@ class _PatientDocumentsState extends State { child: MihButton( onPressed: () async { if (_formKey2.currentState!.validate()) { - await generateMedCert(); + await generateMedCert( + profileProvider, patientManagerProvider); //Navigator.pop(context); } else { MihAlertServices().formNotFilledCompletely(context); @@ -416,7 +336,10 @@ class _PatientDocumentsState extends State { ); } - void prescritionPopUp() { + void prescritionPopUp( + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + ) { showDialog( context: context, barrierDismissible: false, @@ -442,10 +365,10 @@ class _PatientDocumentsState extends State { noDaysController: noDaysController, noRepeatsController: noRepeatsController, outputController: outputController, - selectedPatient: widget.selectedPatient, - signedInUser: widget.signedInUser, - business: widget.business, - businessUser: widget.businessUser, + selectedPatient: patientManagerProvider.selectedPatient!, + signedInUser: profileProvider.user!, + business: profileProvider.business, + businessUser: profileProvider.businessUser, env: env, ), ], @@ -472,8 +395,9 @@ class _PatientDocumentsState extends State { } } - Widget getMenu(double width) { - if (widget.type == "personal") { + Widget getMenu(MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, double width) { + if (patientManagerProvider.personalMode) { return Positioned( right: 10, bottom: 10, @@ -498,7 +422,7 @@ class _PatientDocumentsState extends State { backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - uploudFilePopUp(width); + uploudFilePopUp(patientManagerProvider, width); }, ) ], @@ -529,7 +453,7 @@ class _PatientDocumentsState extends State { backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - uploudFilePopUp(width); + uploudFilePopUp(patientManagerProvider, width); }, ), SpeedDialChild( @@ -549,7 +473,7 @@ class _PatientDocumentsState extends State { backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - medCertPopUp(); + medCertPopUp(profileProvider, patientManagerProvider); }, ), SpeedDialChild( @@ -569,7 +493,7 @@ class _PatientDocumentsState extends State { backgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - prescritionPopUp(); + prescritionPopUp(profileProvider, patientManagerProvider); }, ), ], @@ -578,13 +502,56 @@ class _PatientDocumentsState extends State { } } - void successPopUp(String message) { + void successPopUp(String title, String message) { showDialog( context: context, builder: (context) { - return MIHSuccessMessage( - successType: "Success", - successMessage: message, + return MihPackageAlert( + alertIcon: Icon( + Icons.check_circle_outline_rounded, + size: 150, + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: title, + alertBody: Column( + children: [ + Text( + message, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + context.pop(); + context.pop(); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Dismiss", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ); }, ); @@ -617,7 +584,6 @@ class _PatientDocumentsState extends State { @override void initState() { - futueFiles = fetchFiles(); if (AppEnviroment.getEnv() == "Prod") { env = "Prod"; } else { @@ -636,39 +602,20 @@ class _PatientDocumentsState extends State { } Widget getBody(double width) { - return Stack( - children: [ - MihSingleChildScroll( - child: FutureBuilder( - future: futueFiles, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center( - child: Mihloadingcircle(), - ); - } else if (snapshot.hasData) { - final filesList = snapshot.data!; - return Column(children: [ - BuildFilesList( - files: filesList, - signedInUser: widget.signedInUser, - selectedPatient: widget.selectedPatient, - business: widget.business, - businessUser: widget.businessUser, - type: widget.type, - env: env, - ), - ]); - } else { - return const Center( - child: Text("Error Loading Notes"), - ); - } - }, - ), - ), - getMenu(width), - ], + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + return Stack( + children: [ + MihSingleChildScroll( + child: Column(children: [ + BuildFilesList(), + ]), + ), + getMenu(profileProvider, patientManagerProvider, width), + ], + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_info.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_info.dart similarity index 68% rename from Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_info.dart rename to Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_info.dart index 2f59f61e..a5a04253 100644 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_info.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_info.dart @@ -1,5 +1,4 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart'; -import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; @@ -7,21 +6,16 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/components/mih_edit_patient_details_window.dart'; +import 'package:provider/provider.dart'; class PatientInfo extends StatefulWidget { - final AppUser signedInUser; - final Patient selectedPatient; - final String type; const PatientInfo({ super.key, - required this.signedInUser, - required this.selectedPatient, - required this.type, }); @override @@ -297,6 +291,40 @@ class _PatientInfoState extends State { ); } + void initialiseControllers(PatientManagerProvider patientManagerProvider) { + idController.text = patientManagerProvider.selectedPatient!.id_no; + fnameController.text = patientManagerProvider.selectedPatient!.first_name; + lnameController.text = patientManagerProvider.selectedPatient!.last_name; + cellController.text = patientManagerProvider.selectedPatient!.cell_no; + emailController.text = patientManagerProvider.selectedPatient!.email; + medNameController.text = + patientManagerProvider.selectedPatient!.medical_aid_name; + medNoController.text = + patientManagerProvider.selectedPatient!.medical_aid_no; + medSchemeController.text = + patientManagerProvider.selectedPatient!.medical_aid_scheme; + addressController.text = patientManagerProvider.selectedPatient!.address; + medAidController.text = patientManagerProvider.selectedPatient!.medical_aid; + medMainMemController.text = + patientManagerProvider.selectedPatient!.medical_aid_main_member; + medAidCodeController.text = + patientManagerProvider.selectedPatient!.medical_aid_code; + medAid = patientManagerProvider.selectedPatient!.medical_aid; + if (medAid == "Yes") { + medAidPosition = true; + } else { + medAidPosition = false; + } + } + + void showEditPatientWindow() { + showDialog( + context: context, + builder: (context) { + return MihEditPatientDetailsWindow(); + }); + } + @override void dispose() { idController.dispose(); @@ -316,37 +344,6 @@ class _PatientInfoState extends State { @override void initState() { - setState(() { - idController.value = TextEditingValue(text: widget.selectedPatient.id_no); - fnameController.value = - TextEditingValue(text: widget.selectedPatient.first_name); - lnameController.value = - TextEditingValue(text: widget.selectedPatient.last_name); - cellController.value = - TextEditingValue(text: widget.selectedPatient.cell_no); - emailController.value = - TextEditingValue(text: widget.selectedPatient.email); - medNameController.value = - TextEditingValue(text: widget.selectedPatient.medical_aid_name); - medNoController.value = - TextEditingValue(text: widget.selectedPatient.medical_aid_no); - medSchemeController.value = - TextEditingValue(text: widget.selectedPatient.medical_aid_scheme); - addressController.value = - TextEditingValue(text: widget.selectedPatient.address); - medAidController.value = - TextEditingValue(text: widget.selectedPatient.medical_aid); - medMainMemController.value = TextEditingValue( - text: widget.selectedPatient.medical_aid_main_member); - medAidCodeController.value = - TextEditingValue(text: widget.selectedPatient.medical_aid_code); - medAid = widget.selectedPatient.medical_aid; - }); - if (medAid == "Yes") { - medAidPosition = true; - } else { - medAidPosition = false; - } super.initState(); } @@ -361,21 +358,47 @@ class _PatientInfoState extends State { } Widget getBody(double width) { - return Stack( - children: [ - MihSingleChildScroll( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - MihForm( - formKey: _formKey, - formFields: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - //crossAxisAlignment: , - children: [ - Text( - "Personal", + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + initialiseControllers(patientManagerProvider); + return Stack( + children: [ + MihSingleChildScroll( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + MihForm( + formKey: _formKey, + formFields: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + //crossAxisAlignment: , + children: [ + Text( + "Personal", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ]), + Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark")), + const SizedBox(height: 10), + getPatientDetailsField(), + const SizedBox(height: 10), + Center( + child: Text( + "Medical Aid", textAlign: TextAlign.center, style: TextStyle( fontSize: 25, @@ -385,78 +408,65 @@ class _PatientInfoState extends State { "Dark"), ), ), - ]), - Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark")), - const SizedBox(height: 10), - getPatientDetailsField(), - const SizedBox(height: 10), - Center( - child: Text( - "Medical Aid", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( + ), + Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark")), + const SizedBox(height: 10), + getMedAidDetailsFields(), + ], + ), + ], + ), + ), + Visibility( + visible: patientManagerProvider.personalMode, + child: Positioned( + right: 10, + bottom: 10, + child: MihFloatingMenu( + icon: Icons.add, + animatedIcon: AnimatedIcons.menu_close, + children: [ + SpeedDialChild( + child: Icon( + Icons.edit, + color: MihColors.getPrimaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), - ), - ), - Divider( - color: MihColors.getSecondaryColor( + label: "Edit Profile", + labelBackgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == - "Dark")), - const SizedBox(height: 10), - getMedAidDetailsFields(), - ], - ), - ], - ), - ), - Visibility( - visible: widget.type == "personal", - child: Positioned( - right: 10, - bottom: 10, - child: MihFloatingMenu( - icon: Icons.add, - animatedIcon: AnimatedIcons.menu_close, - children: [ - SpeedDialChild( - child: Icon( - Icons.edit, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - label: "Edit Profile", - labelBackgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - labelStyle: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontWeight: FontWeight.bold, - ), - backgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onTap: () { - context.goNamed( - 'patientProfileEdit', - extra: PatientEditArguments( - widget.signedInUser, - widget.selectedPatient, + "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, ), - ); - }, - ) - ], + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onTap: () { + // context.goNamed( + // 'patientProfileEdit', + // extra: PatientEditArguments( + // profileProvider.user!, + // patientManagerProvider.selectedPatient!, + // ), + // ); + showEditPatientWindow(); + }, + ) + ], + ), + ), ), - ), - ), - ], + ], + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_setup_form.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_setup_form.dart new file mode 100644 index 00000000..c982820a --- /dev/null +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tools/patient_setup_form.dart @@ -0,0 +1,543 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; + +class PatientSetupForm extends StatefulWidget { + const PatientSetupForm({super.key}); + + @override + State createState() => _PatientSetupFormState(); +} + +class _PatientSetupFormState extends State { + final idController = TextEditingController(); + final fnameController = TextEditingController(); + final lnameController = TextEditingController(); + final cellController = TextEditingController(); + final emailController = TextEditingController(); + final medNoController = TextEditingController(); + final medNameController = TextEditingController(); + final medSchemeController = TextEditingController(); + final addressController = TextEditingController(); + final medAidController = TextEditingController(); + final medMainMemController = TextEditingController(); + final medAidCodeController = TextEditingController(); + final _formKey = GlobalKey(); + final FocusNode _focusNode = FocusNode(); + late bool medAidPosition; + late bool medMainMemberPosition; + final ValueNotifier medRequired = ValueNotifier(false); + + Future addPatientService( + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + ) async { + int statusCode = await MihPatientServices().addPatientService( + idController.text, + fnameController.text, + lnameController.text, + emailController.text, + cellController.text, + medAidController.text, + medMainMemController.text, + medNoController.text, + medAidCodeController.text, + medNameController.text, + medSchemeController.text, + addressController.text, + profileProvider, + patientManagerProvider, + ); + if (statusCode == 201) { + String message = + "${fnameController.text} ${lnameController.text} patient profile has been successfully added!\n"; + successPopUp("Successfully created Patient Profile", message); + } else { + internetConnectionPopUp(); + } + } + + void successPopUp(String title, String message) { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.check_circle_outline_rounded, + size: 150, + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: title, + alertBody: Column( + children: [ + Text( + message, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + context.pop(); + context.goNamed( + 'patientProfile', + ); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Dismiss", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + ); + } + + void internetConnectionPopUp() { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Internet Connection"); + }, + ); + } + + void isRequired() { + //print("listerner triggered"); + if (medAidController.text == "Yes") { + medRequired.value = true; + } else { + medRequired.value = false; + } + } + + Widget displayForm(double width) { + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, Widget? child) { + return SingleChildScrollView( + child: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: width * 0.2) + : EdgeInsets.symmetric(horizontal: width * 0.075), + child: Column( + children: [ + MihForm( + formKey: _formKey, + formFields: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Personal", + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 25.0, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ], + ), + Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark")), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: idController, + multiLineInput: false, + requiredText: true, + hintText: "ID No.", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: fnameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "First Name", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: lnameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Surname", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: cellController, + multiLineInput: false, + requiredText: true, + hintText: "Cell No.", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: emailController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Email", + validator: (value) { + return MihValidationServices().validateEmail(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + height: 100, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: addressController, + multiLineInput: true, + requiredText: true, + hintText: "Address", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 15.0), + Center( + child: Text( + "Medical Aid Details", + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 25.0, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + Divider( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark")), + const SizedBox(height: 10.0), + MihToggle( + hintText: "Medical Aid", + initialPostion: medAidPosition, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + secondaryFillColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: (value) { + if (value) { + setState(() { + medAidController.text = "Yes"; + medAidPosition = value; + }); + } else { + setState(() { + medAidController.text = "No"; + medAidPosition = value; + }); + } + }, + ), + ValueListenableBuilder( + valueListenable: medRequired, + builder: + (BuildContext context, bool value, Widget? child) { + return Visibility( + visible: value, + child: Column( + children: [ + const SizedBox(height: 10.0), + MihToggle( + hintText: "Main Member", + initialPostion: medMainMemberPosition, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + secondaryFillColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + onChange: (value) { + if (value) { + setState(() { + medMainMemController.text = "Yes"; + medMainMemberPosition = value; + }); + } else { + setState(() { + medMainMemController.text = "No"; + medMainMemberPosition = value; + }); + } + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + controller: medNoController, + multiLineInput: false, + requiredText: true, + hintText: "No.", + validator: (validationValue) { + if (value) { + return MihValidationServices() + .isEmpty(validationValue); + } + return null; + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + controller: medAidCodeController, + multiLineInput: false, + requiredText: true, + hintText: "Code", + validator: (validationValue) { + if (value) { + return MihValidationServices() + .isEmpty(validationValue); + } + return null; + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + controller: medNameController, + multiLineInput: false, + requiredText: true, + hintText: "Name", + validator: (validationValue) { + if (value) { + return MihValidationServices() + .isEmpty(validationValue); + } + return null; + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + controller: medSchemeController, + multiLineInput: false, + requiredText: true, + hintText: "Plan", + validator: (validationValue) { + if (value) { + return MihValidationServices() + .isEmpty(validationValue); + } + return null; + }, + ), + const SizedBox(height: 10.0), + ], + ), + ); + }, + ), + const SizedBox(height: 20.0), + Center( + child: MihButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + addPatientService( + profileProvider, patientManagerProvider); + } else { + MihAlertServices().formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Add", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + const SizedBox(height: 30.0), + ], + ), + ], + ), + ), + ); + }, + ); + } + + @override + void dispose() { + idController.dispose(); + fnameController.dispose(); + lnameController.dispose(); + cellController.dispose(); + emailController.dispose(); + medNoController.dispose(); + medNameController.dispose(); + medSchemeController.dispose(); + addressController.dispose(); + medAidController.dispose(); + medAidCodeController.removeListener(isRequired); + medRequired.dispose(); + medMainMemController.dispose(); + medAidCodeController.dispose(); + _focusNode.dispose(); + super.dispose(); + } + + @override + void initState() { + medAidController.addListener(isRequired); + MzansiProfileProvider profileProvider = + context.read(); + setState(() { + fnameController.text = profileProvider.user!.fname; + lnameController.text = profileProvider.user!.lname; + emailController.text = profileProvider.user!.email; + medAidPosition = false; + medMainMemberPosition = false; + medAidController.text = "No"; + medMainMemController.text = "No"; + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return displayForm(screenWidth); + } +} diff --git a/Frontend/lib/mih_packages/patient_manager/pat_profile/patient_profile.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/patient_profile.dart new file mode 100644 index 00000000..806ff6d7 --- /dev/null +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/patient_profile.dart @@ -0,0 +1,155 @@ +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/package_tools/patient_claim_or_statement.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/package_tools/patient_consultation.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/package_tools/patient_documents.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/package_tools/patient_info.dart'; +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_claim_statement_generation_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; +import 'package:provider/provider.dart'; + +class PatientProfile extends StatefulWidget { + const PatientProfile({ + super.key, + }); + + @override + State createState() => _PatientProfileState(); +} + +class _PatientProfileState extends State { + bool isLoading = true; + + Future initialisePatientData() async { + setState(() { + isLoading = true; + }); + MzansiProfileProvider profileProvider = + context.read(); + PatientManagerProvider patientManagerProvider = + context.read(); + String? app_id = profileProvider.user!.app_id; + if (patientManagerProvider.selectedPatient == null) { + await MihPatientServices() + .getPatientDetails(app_id, patientManagerProvider); + } + if (patientManagerProvider.selectedPatient == null) { + // go to set up patient package + context.goNamed("patientProfileSetup"); + } else { + await MihPatientServices() + .getPatientConsultationNotes(patientManagerProvider); + await MihPatientServices().getPatientDocuments(patientManagerProvider); + await MIHClaimStatementGenerationApi.getClaimStatementFilesByPatient( + patientManagerProvider); + } + setState(() { + isLoading = false; + }); + } + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) async { + initialisePatientData(); + }); + } + + @override + Widget build(BuildContext context) { + return MihPackage( + appActionButton: getAction(), + appTools: getTools(), + appBody: getToolBody(), + appToolTitles: getToolTitle(), + selectedbodyIndex: + context.watch().patientProfileIndex, + onIndexChange: (newValue) { + context.read().setPatientProfileIndex(newValue); + }, + ); + } + + MihPackageAction getAction() { + PatientManagerProvider patientManagerProvider = + context.read(); + return MihPackageAction( + icon: const Icon(Icons.arrow_back), + iconSize: 35, + onTap: () { + patientManagerProvider.setPatientProfileIndex(0); + if (!patientManagerProvider.personalMode) { + context.pop(); + } else { + context.goNamed( + 'mihHome', + ); + } + FocusScope.of(context).unfocus(); + }, + ); + } + + MihPackageTools getTools() { + PatientManagerProvider patientManagerProvider = + context.read(); + Map temp = {}; + temp[const Icon(Icons.perm_identity)] = () { + patientManagerProvider.setPatientProfileIndex(0); + }; + temp[const Icon(Icons.article_outlined)] = () { + patientManagerProvider.setPatientProfileIndex(1); + }; + temp[const Icon(Icons.file_present)] = () { + patientManagerProvider.setPatientProfileIndex(2); + }; + temp[const Icon(Icons.file_open_outlined)] = () { + patientManagerProvider.setPatientProfileIndex(3); + }; + return MihPackageTools( + tools: temp, + selcetedIndex: patientManagerProvider.patientProfileIndex, + ); + } + + List getToolBody() { + if (isLoading) { + return [ + Center( + child: Mihloadingcircle(), + ), + ]; + } + PatientManagerProvider patientManagerProvider = + context.read(); + if (patientManagerProvider.selectedPatient == null) { + return [ + const SizedBox(), + ]; + } + List toolBodies = [ + PatientInfo(), + PatientConsultation(), + PatientDocuments(), + PatientClaimOrStatement(), + ]; + return toolBodies; + } + + List getToolTitle() { + List toolTitles = [ + "Details", + "Notes", + "Documents", + "Claims", + ]; + return toolTitles; + } +} diff --git a/Frontend/lib/mih_packages/patient_manager/pat_profile/patient_set_up.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/patient_set_up.dart new file mode 100644 index 00000000..5f4f319d --- /dev/null +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/patient_set_up.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; +import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/package_tools/patient_setup_form.dart'; +import 'package:provider/provider.dart'; + +class PatientSetUp extends StatefulWidget { + const PatientSetUp({super.key}); + + @override + State createState() => _PatientSetUpState(); +} + +class _PatientSetUpState extends State { + @override + Widget build(BuildContext context) { + return MihPackage( + appActionButton: getAction(), + appTools: getTools(), + appBody: getToolBody(), + appToolTitles: getToolTitle(), + selectedbodyIndex: + context.watch().patientProfileIndex, + onIndexChange: (newValue) { + context.read().setPatientProfileIndex(newValue); + }, + ); + } + + MihPackageAction getAction() { + return MihPackageAction( + icon: const Icon(Icons.arrow_back), + iconSize: 35, + onTap: () { + context.goNamed( + 'mihHome', + ); + FocusScope.of(context).unfocus(); + }, + ); + } + + MihPackageTools getTools() { + PatientManagerProvider patientManagerProvider = + context.read(); + Map temp = {}; + temp[const Icon(Icons.medical_services)] = () { + patientManagerProvider.setPatientProfileIndex(0); + }; + return MihPackageTools( + tools: temp, + selcetedIndex: patientManagerProvider.patientProfileIndex, + ); + } + + List getToolBody() { + List toolBodies = [ + PatientSetupForm(), + ]; + return toolBodies; + } + + List getToolTitle() { + List toolTitles = [ + "Set Up Patient Profile", + ]; + return toolTitles; + } +} diff --git a/Frontend/lib/mih_packages/patient_profile/pat_manager/pat_manager.dart b/Frontend/lib/mih_packages/patient_profile/pat_manager/pat_manager.dart deleted file mode 100644 index 77003af1..00000000 --- a/Frontend/lib/mih_packages/patient_profile/pat_manager/pat_manager.dart +++ /dev/null @@ -1,126 +0,0 @@ -import 'package:go_router/go_router.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/package_tools/mih_patient_search.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/package_tools/my_patient_list.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/package_tools/waiting_room.dart'; -import 'package:flutter/material.dart'; - -class PatManager extends StatefulWidget { - final PatManagerArguments arguments; - const PatManager({ - super.key, - required this.arguments, - }); - - @override - State createState() => _PatManagerState(); -} - -class _PatManagerState extends State { - int _selcetedIndex = 0; - - void updateIndex(int index) { - setState(() { - _selcetedIndex = index; - }); - } - - @override - Widget build(BuildContext context) { - return MihPackage( - appActionButton: getActionButton(), - appTools: getTools(), - appBody: getToolBody(), - appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); - }, - ); - } - - MihPackageAction getActionButton() { - return MihPackageAction( - icon: const Icon(Icons.arrow_back), - iconSize: 35, - onTap: () { - // Navigator.of(context).pop(); - context.goNamed( - 'mihHome', - extra: false, - ); - FocusScope.of(context).unfocus(); - }, - ); - } - - MihPackageTools getTools() { - Map temp = {}; - temp[const Icon(Icons.calendar_month)] = () { - setState(() { - _selcetedIndex = 0; - }); - }; - - temp[const Icon(Icons.check_box_outlined)] = () { - setState(() { - _selcetedIndex = 1; - }); - }; - - temp[const Icon(Icons.search)] = () { - setState(() { - _selcetedIndex = 2; - }); - }; - return MihPackageTools( - tools: temp, - selcetedIndex: _selcetedIndex, - ); - } - - List getToolBody() { - List toolBodies = [ - //appointment here - // Appointments( - // signedInUser: widget.arguments.signedInUser, - // business: widget.arguments.business, - // personalSelected: widget.arguments.personalSelected, - // ), - WaitingRoom( - signedInUser: widget.arguments.signedInUser, - business: widget.arguments.business, - businessUser: widget.arguments.businessUser, - personalSelected: widget.arguments.personalSelected, - onIndexChange: updateIndex, - ), - MyPatientList( - signedInUser: widget.arguments.signedInUser, - business: widget.arguments.business, - businessUser: widget.arguments.businessUser, - personalSelected: widget.arguments.personalSelected, - ), - MihPatientSearch( - signedInUser: widget.arguments.signedInUser, - business: widget.arguments.business, - personalSelected: widget.arguments.personalSelected, - businessUser: widget.arguments.businessUser, - ), - ]; - return toolBodies; - } - - List getToolTitle() { - List toolTitles = [ - "Waiting Room", - "My Patients", - "Search Patients", - ]; - return toolTitles; - } -} diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/add_or_view_patient.dart b/Frontend/lib/mih_packages/patient_profile/pat_profile/add_or_view_patient.dart deleted file mode 100644 index c7a6455a..00000000 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/add_or_view_patient.dart +++ /dev/null @@ -1,79 +0,0 @@ -import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/patient_add.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/patient_profile.dart'; -import 'package:flutter/material.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; - -class AddOrViewPatient extends StatefulWidget { - //final AppUser signedInUser; - final PatientViewArguments arguments; - const AddOrViewPatient({ - super.key, - required this.arguments, - }); - - @override - State createState() => _AddOrViewPatientState(); -} - -class _AddOrViewPatientState extends State { - late double width; - late double height; - late Widget loading; - late Future patient; - - Future fetchPatientData() async { - return await MihPatientServices() - .getPatientDetails(widget.arguments.signedInUser.app_id); - } - - @override - void initState() { - super.initState(); - patient = fetchPatientData(); - } - - @override - Widget build(BuildContext context) { - print("AddOrViewPatient"); - var size = MediaQuery.of(context).size; - setState(() { - width = size.width; - height = size.height; - }); - return FutureBuilder( - future: patient, - builder: (ctx, snapshot) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - // Extracting data from snapshot object - //final data = snapshot.data as String; - return PatientProfile( - arguments: PatientViewArguments( - widget.arguments.signedInUser, - snapshot.requireData, - null, - null, - widget.arguments.type, - )); - } else if (snapshot.connectionState == ConnectionState.waiting) { - loading = Container( - width: width, - height: height, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - child: const Mihloadingcircle(), - ); - - return loading; - } else { - return AddPatient(signedInUser: widget.arguments.signedInUser); - } - }, - ); - } -} diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/components/claim_statement_window.dart b/Frontend/lib/mih_packages/patient_profile/pat_profile/components/claim_statement_window.dart deleted file mode 100644 index 39da94a6..00000000 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/components/claim_statement_window.dart +++ /dev/null @@ -1,536 +0,0 @@ -import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_claim_statement_generation_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_icd10_code_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_date_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_radio_options.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/icd10_code.dart.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/components/icd10_search_window.dart'; -import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; - -class ClaimStatementWindow extends StatefulWidget { - final Patient selectedPatient; - final AppUser signedInUser; - final Business? business; - final BusinessUser? businessUser; - final String env; - const ClaimStatementWindow({ - super.key, - required this.selectedPatient, - required this.signedInUser, - required this.business, - required this.businessUser, - required this.env, - }); - - @override - State createState() => _ClaimStatementWindowState(); -} - -class _ClaimStatementWindowState extends State { - final TextEditingController _docTypeController = TextEditingController(); - final TextEditingController _fullNameController = TextEditingController(); - final TextEditingController _idController = TextEditingController(); - final TextEditingController _medAidController = TextEditingController(); - final TextEditingController _medAidNoController = TextEditingController(); - final TextEditingController _medAidCodeController = TextEditingController(); - final TextEditingController _medAidNameController = TextEditingController(); - final TextEditingController _medAidSchemeController = TextEditingController(); - final TextEditingController _providerNameController = TextEditingController(); - final TextEditingController _practiceNoController = TextEditingController(); - final TextEditingController _vatNoController = TextEditingController(); - final TextEditingController _serviceDateController = TextEditingController(); - final TextEditingController _serviceDescController = TextEditingController(); - final TextEditingController _serviceDescOptionsController = - TextEditingController(); - final TextEditingController _prcedureNameController = TextEditingController(); - // final TextEditingController _procedureDateController = - // TextEditingController(); - final TextEditingController _proceedureAdditionalInfoController = - TextEditingController(); - final TextEditingController _icd10CodeController = TextEditingController(); - final TextEditingController _amountController = TextEditingController(); - final TextEditingController _preauthNoController = TextEditingController(); - final ValueNotifier serviceDesc = ValueNotifier(""); - final ValueNotifier medAid = ValueNotifier(""); - List icd10codeList = []; - final FocusNode _searchFocusNode = FocusNode(); - final _formKey = GlobalKey(); - - void icd10SearchWindow(List codeList) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => ICD10SearchWindow( - icd10CodeController: _icd10CodeController, - icd10codeList: codeList, - ), - ); - } - - Widget getWindowBody(double width) { - return Padding( - padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.05) - : const EdgeInsets.symmetric(horizontal: 0), - child: Column( - children: [ - MihForm( - formKey: _formKey, - formFields: [ - MihRadioOptions( - controller: _docTypeController, - hintText: "Document Type", - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - secondaryFillColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - requiredText: true, - radioOptions: const ["Claim", "Statement"], - ), - const SizedBox(height: 10), - Center( - child: Text( - "Service Details", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - ), - Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark")), - const SizedBox(height: 10), - MihDateField( - controller: _serviceDateController, - labelText: "Date of Service", - required: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10), - MihRadioOptions( - controller: _serviceDescController, - hintText: "Serviced Description", - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - secondaryFillColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - requiredText: true, - radioOptions: const [ - "Consultation", - "Procedure", - "Other", - ], - ), - const SizedBox(height: 10), - ValueListenableBuilder( - valueListenable: serviceDesc, - builder: (BuildContext context, String value, Widget? child) { - Widget returnWidget; - switch (value) { - case 'Consultation': - returnWidget = Column( - key: const ValueKey('consultation_fields'), // Added key - children: [ - MihRadioOptions( - key: const ValueKey('consultation_type_dropdown'), - controller: _serviceDescOptionsController, - hintText: "Consultation Type", - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - secondaryFillColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - requiredText: true, - radioOptions: const [ - "General Consultation", - "Follow-Up Consultation", - "Specialist Consultation", - "Emergency Consultation", - ], - ), - const SizedBox(height: 10), - ], - ); - break; - case 'Procedure': - returnWidget = Column( - key: const ValueKey('procedure_fields'), // Added key - children: [ - MihTextFormField( - key: const ValueKey( - 'procedure_name_field'), // Added key - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: _prcedureNameController, - multiLineInput: false, - requiredText: true, - hintText: "Procedure Name", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10), - MihTextFormField( - key: const ValueKey( - 'procedure_additional_info_field'), // Added key - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: _proceedureAdditionalInfoController, - multiLineInput: false, - requiredText: true, - hintText: "Additional Procedure Information", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 15), - ], - ); - break; - case 'Other': - returnWidget = Column( - key: const ValueKey('other_fields'), // Added key - children: [ - MihTextFormField( - key: const ValueKey( - 'other_service_description_field'), // Added key - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: _serviceDescOptionsController, - multiLineInput: false, - requiredText: true, - hintText: "Service Description Details", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10), - ], - ); - break; - default: - returnWidget = const SizedBox( - key: const ValueKey('empty_fields')); // Added key - } - return returnWidget; - }, - ), - Column( - children: [ - Align( - alignment: Alignment.centerLeft, - child: Text("ICD-10 Code & Description", - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - )), - ), - const SizedBox(height: 4), - MihSearchBar( - controller: _icd10CodeController, - hintText: "ICD-10 Search", - prefixIcon: Icons.search, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - hintColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onPrefixIconTap: () { - MIHIcd10CodeApis.getIcd10Codes( - _icd10CodeController.text, context) - .then((result) { - icd10SearchWindow(result); - }); - }, - onClearIconTap: () { - _icd10CodeController.clear(); - }, - searchFocusNode: _searchFocusNode, - ), - ], - ), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: _amountController, - multiLineInput: false, - requiredText: true, - numberMode: true, - hintText: "Service Cost", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10), - Center( - child: Text( - "Additional Infomation", - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - ), - Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark")), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: _preauthNoController, - multiLineInput: false, - requiredText: false, - hintText: "Pre-authorisation No.", - ), - const SizedBox(height: 20), - Center( - child: MihButton( - onPressed: () { - if (_formKey.currentState!.validate()) { - if (isInputValid()) { - MIHClaimStatementGenerationApi().generateClaimStatement( - ClaimStatementGenerationArguments( - _docTypeController.text, - widget.selectedPatient.app_id, - _fullNameController.text, - _idController.text, - _medAidController.text, - _medAidNoController.text, - _medAidCodeController.text, - _medAidNameController.text, - _medAidSchemeController.text, - widget.business!.Name, - "*To-Be Added*", - widget.business!.contact_no, - widget.business!.bus_email, - _providerNameController.text, - _practiceNoController.text, - _vatNoController.text, - _serviceDateController.text, - _serviceDescController.text, - _serviceDescOptionsController.text, - _prcedureNameController.text, - _proceedureAdditionalInfoController.text, - _icd10CodeController.text, - _amountController.text, - _preauthNoController.text, - widget.business!.logo_path, - widget.businessUser!.sig_path, - ), - PatientViewArguments( - widget.signedInUser, - widget.selectedPatient, - widget.businessUser, - widget.business, - "business", - ), - widget.env, - context); - } else { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage( - errorType: "Input Error"); - }, - ); - } - } else { - MihAlertServices().formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Text( - "Generate", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ], - ), - ); - } - - void serviceDescriptionSelected() { - String selectedType = _serviceDescController.text; - serviceDesc.value = selectedType; - if (selectedType == 'Consultation') { - _prcedureNameController.clear(); - _proceedureAdditionalInfoController.clear(); - } else if (selectedType == 'Procedure') { - _serviceDescOptionsController.clear(); - } else if (selectedType == 'Other') { - _prcedureNameController.clear(); - _proceedureAdditionalInfoController.clear(); - } else { - _prcedureNameController.clear(); - _proceedureAdditionalInfoController.clear(); - _serviceDescOptionsController.clear(); - } - } - - void hasMedAid() { - if (_medAidController.text.isNotEmpty) { - } else { - medAid.value = ""; - } - } - - bool isInputValid() { - if (_docTypeController.text.isEmpty || - _serviceDateController.text.isEmpty || - _icd10CodeController.text.isEmpty || - _amountController.text.isEmpty) { - return false; - } - switch (_serviceDescController.text) { - case 'Consultation': - case 'Other': - if (_serviceDescOptionsController.text.isEmpty) { - return false; - } - break; - case 'Procedure': - if (_prcedureNameController.text.isEmpty || - _proceedureAdditionalInfoController.text.isEmpty) { - return false; - } - break; - default: - return false; - } - return true; - } - - String getUserTitle() { - if (widget.businessUser!.title == "Doctor") { - return "Dr."; - } else { - return widget.businessUser!.title; - } - } - - String getTodayDate() { - DateTime today = DateTime.now(); - return DateFormat('yyyy-MM-dd').format(today); - } - - @override - void dispose() { - _docTypeController.dispose(); - _fullNameController.dispose(); - _idController.dispose(); - _medAidController.dispose(); - _medAidNoController.dispose(); - _medAidCodeController.dispose(); - _medAidNameController.dispose(); - _medAidSchemeController.dispose(); - _providerNameController.dispose(); - _practiceNoController.dispose(); - _vatNoController.dispose(); - _serviceDateController.dispose(); - _serviceDescController.dispose(); - _serviceDescOptionsController.dispose(); - _prcedureNameController.dispose(); - // _procedureDateController.dispose(); - _proceedureAdditionalInfoController.dispose(); - _icd10CodeController.dispose(); - _preauthNoController.dispose(); - _searchFocusNode.dispose(); - serviceDesc.dispose(); - medAid.dispose(); - super.dispose(); - } - - @override - void initState() { - super.initState(); - - _serviceDescController.text = "Consultation"; - _serviceDescController.addListener(serviceDescriptionSelected); - serviceDesc.value = "Consultation"; - _medAidController.addListener(hasMedAid); - _fullNameController.text = - "${widget.selectedPatient.first_name} ${widget.selectedPatient.last_name}"; - _idController.text = widget.selectedPatient.id_no; - _medAidController.text = widget.selectedPatient.medical_aid; - _medAidNameController.text = widget.selectedPatient.medical_aid_name; - _medAidCodeController.text = widget.selectedPatient.medical_aid_code; - _medAidNoController.text = widget.selectedPatient.medical_aid_no; - _medAidSchemeController.text = widget.selectedPatient.medical_aid_scheme; - _serviceDateController.text = getTodayDate(); - _providerNameController.text = - "${getUserTitle()} ${widget.signedInUser.fname} ${widget.signedInUser.lname}"; - _practiceNoController.text = widget.business!.practice_no; - _vatNoController.text = widget.business!.vat_no; - hasMedAid(); - } - - @override - Widget build(BuildContext context) { - double screenWidth = MediaQuery.of(context).size.width; - return MihPackageWindow( - fullscreen: false, - windowTitle: "Generate Claim/ Statement Document", - onWindowTapClose: () { - Navigator.pop(context); - }, - windowBody: getWindowBody(screenWidth), - ); - } -} diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_claim_or_statement.dart b/Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_claim_or_statement.dart deleted file mode 100644 index c26c0480..00000000 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/package_tools/patient_claim_or_statement.dart +++ /dev/null @@ -1,154 +0,0 @@ -import 'package:flutter_speed_dial/flutter_speed_dial.dart'; -import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_claim_statement_generation_services.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/claim_statement_file.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/components/claim_statement_window.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/list_builders/build_claim_statement_files_list.dart'; -import 'package:flutter/material.dart'; - -class PatientClaimOrStatement extends StatefulWidget { - final int patientIndex; - final Patient selectedPatient; - final AppUser signedInUser; - final Business? business; - final BusinessUser? businessUser; - final String type; - const PatientClaimOrStatement({ - super.key, - required this.patientIndex, - required this.selectedPatient, - required this.signedInUser, - required this.business, - required this.businessUser, - required this.type, - }); - - @override - State createState() => - _PatientClaimOrStatementState(); -} - -class _PatientClaimOrStatementState extends State { - late Future> futueFiles; - late String env; - - void claimOrStatementWindow() { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => ClaimStatementWindow( - selectedPatient: widget.selectedPatient, - signedInUser: widget.signedInUser, - business: widget.business, - businessUser: widget.businessUser, - env: env, - ), - ); - } - - @override - void initState() { - if (widget.business == null) { - futueFiles = - MIHClaimStatementGenerationApi.getClaimStatementFilesByPatient( - widget.signedInUser.app_id); - } else { - futueFiles = - MIHClaimStatementGenerationApi.getClaimStatementFilesByBusiness( - widget.business!.business_id); - } - if (AppEnviroment.getEnv() == "Prod") { - env = "Prod"; - } else { - env = "Dev"; - } - super.initState(); - } - - @override - Widget build(BuildContext context) { - return MihPackageToolBody( - borderOn: false, - bodyItem: getBody(), - ); - } - - Widget getBody() { - return Stack( - children: [ - FutureBuilder( - future: futueFiles, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const Center( - child: Mihloadingcircle(), - ); - } else if (snapshot.hasData) { - final filesList = snapshot.data!; - return Column( - children: [ - //const Placeholder(), - BuildClaimStatementFileList( - files: filesList, - signedInUser: widget.signedInUser, - selectedPatient: widget.selectedPatient, - business: widget.business, - businessUser: widget.businessUser, - type: widget.type, - env: env, - ), - ], - ); - } else { - return const Center( - child: Text("Error Loading Notes"), - ); - } - }, - ), - Visibility( - visible: widget.type != "personal", - child: Positioned( - right: 10, - bottom: 10, - child: MihFloatingMenu( - icon: Icons.file_copy, - animatedIcon: AnimatedIcons.menu_close, - children: [ - SpeedDialChild( - child: Icon( - Icons.add, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - label: "Generate Claim/ Statement", - labelBackgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - labelStyle: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontWeight: FontWeight.bold, - ), - backgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onTap: () { - claimOrStatementWindow(); - }, - ) - ], - ), - ), - ), - ], - ); - } -} diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/patient_edit.dart b/Frontend/lib/mih_packages/patient_profile/pat_profile/patient_edit.dart deleted file mode 100644 index 1de1d5e4..00000000 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/patient_edit.dart +++ /dev/null @@ -1,903 +0,0 @@ -import 'dart:convert'; - -import 'package:go_router/go_router.dart'; -import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; -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_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:supertokens_flutter/supertokens.dart'; -import 'package:supertokens_flutter/http.dart' as http; - -class EditPatient extends StatefulWidget { - final Patient selectedPatient; - final AppUser signedInUser; - const EditPatient({ - super.key, - required this.selectedPatient, - required this.signedInUser, - }); - - @override - State createState() => _EditPatientState(); -} - -class _EditPatientState extends State { - var idController = TextEditingController(); - final fnameController = TextEditingController(); - final lnameController = TextEditingController(); - final cellController = TextEditingController(); - final emailController = TextEditingController(); - final medNoController = TextEditingController(); - final medNameController = TextEditingController(); - final medSchemeController = TextEditingController(); - final addressController = TextEditingController(); - final medAidController = TextEditingController(); - final medMainMemController = TextEditingController(); - final medAidCodeController = TextEditingController(); - final baseAPI = AppEnviroment.baseApiUrl; - final docOfficeIdApiUrl = "${AppEnviroment.baseApiUrl}/users/profile/"; - final apiUrlEdit = "${AppEnviroment.baseApiUrl}/patients/update/"; - final apiUrlDelete = "${AppEnviroment.baseApiUrl}/patients/delete/"; - final _formKey = GlobalKey(); - - late bool medAidPosition; - late bool medMainMemberPosition; - late int futureDocOfficeId; - late String userEmail; - // bool medRequired = false; - final ValueNotifier medRequired = ValueNotifier(false); - - late double width; - late double height; - - final FocusNode _focusNode = FocusNode(); - - // Future getOfficeIdByUser(String endpoint) async { - // final response = await http.get(Uri.parse(endpoint)); - // if (response.statusCode == 200) { - // String body = response.body; - // var decodedData = jsonDecode(body); - // AppUser u = AppUser.fromJson(decodedData as Map); - // setState(() { - // //futureDocOfficeId = u.docOffice_id; - // //print(futureDocOfficeId); - // }); - // } else { - // internetConnectionPopUp(); - // throw Exception('failed to load patients'); - // } - // } - - Future updatePatientApiCall() async { - var statusCode = await MihPatientServices().updatePatientService( - widget.selectedPatient.app_id, - idController.text, - fnameController.text, - lnameController.text, - emailController.text, - cellController.text, - medAidController.text, - medMainMemController.text, - medNoController.text, - medAidCodeController.text, - medNameController.text, - medSchemeController.text, - addressController.text, - ); - if (statusCode == 200) { - successPopUp( - "Successfully Updated Profile!", - "${fnameController.text} ${lnameController.text}'s information has been updated successfully! Their medical records and details are now current.", - ); - } else { - MihAlertServices().errorAlert( - "Error Updating Profile", - "There was an error updating your profile. Please try again later.", - context, - ); - } - // var response = await http.put( - // Uri.parse(apiUrlEdit), - // headers: { - // "Content-Type": "application/json; charset=UTF-8" - // }, - // body: jsonEncode({ - // "id_no": idController.text, - // "first_name": fnameController.text, - // "last_name": lnameController.text, - // "email": emailController.text, - // "cell_no": cellController.text, - // "medical_aid": medAidController.text, - // "medical_aid_main_member": medMainMemController.text, - // "medical_aid_no": medNoController.text, - // "medical_aid_code": medAidCodeController.text, - // "medical_aid_name": medNameController.text, - // "medical_aid_scheme": medSchemeController.text, - // "address": addressController.text, - // "app_id": widget.selectedPatient.app_id, - // }), - // ); - // print(response.statusCode); - // if (response.statusCode == 200) { - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pushNamed('/patient-profile', - // arguments: PatientViewArguments( - // widget.signedInUser, null, null, null, "personal")); - // //Navigator.of(context).pushNamed('/'); - // String message = - // "${fnameController.text} ${lnameController.text}'s information has been updated successfully! Their medical records and details are now current."; - // successPopUp(message); - // } else { - // internetConnectionPopUp(); - // } - } - - void successPopUp(String title, String message) { - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.check_circle_outline_rounded, - size: 150, - color: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: title, - alertBody: Column( - children: [ - Text( - message, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 15, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 25), - Center( - child: MihButton( - onPressed: () { - context.goNamed( - "patientProfile", - extra: PatientViewArguments( - widget.signedInUser, - widget.selectedPatient, - null, - null, - "personal", - ), - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - elevation: 10, - width: 300, - child: Text( - "Dismiss", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ) - ], - ), - alertColour: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - // return MIHSuccessMessage( - // successType: "Success", - // successMessage: message, - // ); - }, - ); - } - - Future deletePatientApiCall() async { - //print("Here1"); - //userEmail = getLoginUserEmail() as String; - //print(userEmail); - //print("Here2"); - //await getOfficeIdByUser(docOfficeIdApiUrl + userEmail); - //print("Office ID: ${futureDocOfficeId.toString()}"); - //print("OPatient ID No: ${idController.text}"); - //print("Here3"); - var response = await http.delete( - Uri.parse(apiUrlDelete), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode( - {"app_id": widget.selectedPatient.app_id}), - ); - //print("Here4"); - //print(response.statusCode); - if (response.statusCode == 200) { - Navigator.of(context).pop(); - Navigator.of(context).pop(); - Navigator.of(context).popAndPushNamed('/patient-profile', - arguments: PatientViewArguments( - widget.signedInUser, null, null, null, "personal")); - String message = - "${fnameController.text} ${lnameController.text}'s record has been deleted successfully. This means it will no longer be visible in patient manager and cannot be used for future appointments."; - successPopUp("Error", message); - } else { - internetConnectionPopUp(); - } - } - - Future getLoginUserEmail() async { - var uid = await SuperTokens.getUserId(); - var response = await http.get(Uri.parse("$baseAPI/user/$uid")); - if (response.statusCode == 200) { - var user = jsonDecode(response.body); - userEmail = user["email"]; - } - } - - void messagePopUp(error) { - showDialog( - context: context, - builder: (context) { - return AlertDialog( - title: Text(error), - ); - }, - ); - } - - void internetConnectionPopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); - } - - void deletePatientPopUp() { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => Dialog( - child: Stack( - children: [ - Container( - padding: const EdgeInsets.all(10.0), - width: 700.0, - height: (height / 3) * 2, - decoration: BoxDecoration( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - borderRadius: BorderRadius.circular(25.0), - border: Border.all( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 5.0), - ), - child: SingleChildScrollView( - child: Column( - //mainAxisSize: MainAxisSize.max, - children: [ - Icon( - Icons.warning_amber_rounded, - size: 100, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - const SizedBox(height: 15), - Text( - "Are you sure you want to delete this?", - textAlign: TextAlign.center, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 25.0, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 25.0), - child: Text( - "This action is permanent! Deleting ${fnameController.text} ${lnameController.text} will remove him\\her from your account. You won't be able to recover it once it's gone.", - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 15.0, - fontWeight: FontWeight.bold, - ), - ), - ), - const SizedBox(height: 15), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 25.0), - child: Text( - "Here's what you'll be deleting:", - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20.0, - fontWeight: FontWeight.bold, - ), - ), - ), - const SizedBox(height: 10), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 25.0), - child: SizedBox( - width: 450, - child: Text( - "1) Patient Profile Information.\n2) Patient Notes\n3) Patient Files.", - textAlign: TextAlign.left, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 15.0, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - MihButton( - onPressed: deletePatientApiCall, - buttonColor: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - width: 300, - child: Text( - "Delete", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ), - ), - Positioned( - top: 5, - right: 5, - width: 50, - height: 50, - child: IconButton( - onPressed: () { - Navigator.pop(context); - }, - icon: Icon( - Icons.close, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - size: 35, - ), - ), - ), - ], - ), - ), - ); - } - - bool isFieldsFilled() { - if (medRequired.value) { - if (idController.text.isEmpty || - fnameController.text.isEmpty || - lnameController.text.isEmpty || - cellController.text.isEmpty || - emailController.text.isEmpty || - medNoController.text.isEmpty || - medNameController.text.isEmpty || - medSchemeController.text.isEmpty || - addressController.text.isEmpty || - medAidController.text.isEmpty || - medMainMemController.text.isEmpty || - medAidCodeController.text.isEmpty) { - return false; - } else { - return true; - } - } else { - if (idController.text.isEmpty || - fnameController.text.isEmpty || - lnameController.text.isEmpty || - cellController.text.isEmpty || - emailController.text.isEmpty || - addressController.text.isEmpty || - medAidController.text.isEmpty) { - return false; - } else { - return true; - } - } - } - - void isRequired() { - print("listerner triggered"); - if (medAidController.text == "Yes") { - medRequired.value = true; - } else if (medAidController.text == "No") { - medRequired.value = false; - } else { - //print("here"); - } - } - - Widget displayForm(double width) { - return SingleChildScrollView( - child: Padding( - padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.2) - : EdgeInsets.symmetric(horizontal: width * 0.075), - child: Column( - children: [ - MihForm( - formKey: _formKey, - formFields: [ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - "Personal", - textAlign: TextAlign.center, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 25.0, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - ], - ), - Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark")), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: idController, - multiLineInput: false, - requiredText: true, - hintText: "ID No.", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: fnameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "First Name", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: lnameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Surname", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: cellController, - multiLineInput: false, - requiredText: true, - hintText: "Cell No.", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: emailController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Email", - validator: (value) { - return MihValidationServices().validateEmail(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - height: 100, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: addressController, - multiLineInput: true, - requiredText: true, - hintText: "Address", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 15.0), - Center( - child: Text( - "Medical Aid Details", - textAlign: TextAlign.center, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 25.0, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - ), - ), - Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark")), - const SizedBox(height: 10.0), - MihToggle( - hintText: "Medical Aid", - initialPostion: medAidPosition, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - secondaryFillColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onChange: (value) { - if (value) { - setState(() { - medAidController.text = "Yes"; - medAidPosition = value; - }); - } else { - setState(() { - medAidController.text = "No"; - medAidPosition = value; - }); - } - }, - ), - ValueListenableBuilder( - valueListenable: medRequired, - builder: (BuildContext context, bool value, Widget? child) { - return Visibility( - visible: value, - child: Column( - children: [ - const SizedBox(height: 10.0), - MihToggle( - hintText: "Main Member", - initialPostion: medMainMemberPosition, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - secondaryFillColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - onChange: (value) { - if (value) { - setState(() { - medMainMemController.text = "Yes"; - medMainMemberPosition = value; - }); - } else { - setState(() { - medMainMemController.text = "No"; - medMainMemberPosition = value; - }); - } - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: medNoController, - multiLineInput: false, - requiredText: true, - hintText: "No.", - validator: (validationValue) { - if (value) { - return MihValidationServices() - .isEmpty(validationValue); - } - return null; - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: medAidCodeController, - multiLineInput: false, - requiredText: true, - hintText: "Code", - validator: (validationValue) { - if (value) { - return MihValidationServices() - .isEmpty(validationValue); - } - return null; - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: medNameController, - multiLineInput: false, - requiredText: true, - hintText: "Name", - validator: (validationValue) { - if (value) { - return MihValidationServices() - .isEmpty(validationValue); - } - return null; - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: medSchemeController, - multiLineInput: false, - requiredText: true, - hintText: "Plan", - validator: (validationValue) { - if (value) { - return MihValidationServices() - .isEmpty(validationValue); - } - return null; - }, - ), - const SizedBox(height: 10.0), - ], - ), - ); - }, - ), - const SizedBox(height: 20.0), - Center( - child: MihButton( - onPressed: () { - if (_formKey.currentState!.validate()) { - submitForm(); - } else { - MihAlertServices().formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Text( - "Update", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - const SizedBox(height: 20.0), - ], - ), - ], - ), - ), - ); - } - - void submitForm() { - updatePatientApiCall(); - } - - MIHAction getActionButton() { - return MIHAction( - icon: const Icon(Icons.arrow_back), - iconSize: 35, - onTap: () { - context.goNamed( - 'patientProfile', - extra: PatientViewArguments( - widget.signedInUser, - null, - null, - null, - "personal", - ), - ); - // Navigator.of(context).pop(); - }, - ); - } - - MIHHeader getHeader() { - return const MIHHeader( - headerAlignment: MainAxisAlignment.center, - headerItems: [ - Text( - "Edit Patient Details", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 25, - ), - ), - ], - ); - } - - MIHBody getBody(double width) { - return MIHBody( - borderOn: false, - bodyItems: [ - KeyboardListener( - focusNode: _focusNode, - autofocus: true, - onKeyEvent: (event) async { - if (event is KeyDownEvent && - event.logicalKey == LogicalKeyboardKey.enter) { - if (_formKey.currentState!.validate()) { - submitForm(); - } else { - MihAlertServices().formNotFilledCompletely(context); - } - } - }, - child: displayForm(width), - ), - ], - ); - } - - @override - void dispose() { - idController.dispose(); - fnameController.dispose(); - lnameController.dispose(); - cellController.dispose(); - emailController.dispose(); - medNoController.dispose(); - medNameController.dispose(); - medSchemeController.dispose(); - addressController.dispose(); - medAidController.dispose(); - medAidCodeController.removeListener(isRequired); - medMainMemController.dispose(); - medAidCodeController.dispose(); - medRequired.dispose(); - _focusNode.dispose(); - super.dispose(); - } - - @override - void initState() { - getLoginUserEmail(); - medAidController.addListener(isRequired); - setState(() { - 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; - }); - - if (medAidController.text == "Yes") { - medAidPosition = true; - } else { - medAidPosition = false; - medAidController.text = "No"; - } - if (medMainMemController.text == "Yes") { - medMainMemberPosition = true; - } else { - medMainMemberPosition = false; - medMainMemController.text = "No"; - } - super.initState(); - } - - @override - Widget build(BuildContext context) { - var size = MediaQuery.of(context).size; - setState(() { - width = size.width; - height = size.height; - }); - return MIHLayoutBuilder( - actionButton: getActionButton(), - header: getHeader(), - secondaryActionButton: null, - body: getBody(width), - actionDrawer: null, - secondaryActionDrawer: null, - bottomNavBar: null, - pullDownToRefresh: false, - onPullDown: () async {}, - ); - } -} diff --git a/Frontend/lib/mih_packages/patient_profile/pat_profile/patient_profile.dart b/Frontend/lib/mih_packages/patient_profile/pat_profile/patient_profile.dart deleted file mode 100644 index 01f3d6b6..00000000 --- a/Frontend/lib/mih_packages/patient_profile/pat_profile/patient_profile.dart +++ /dev/null @@ -1,131 +0,0 @@ -import 'package:go_router/go_router.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/package_tools/patient_claim_or_statement.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/package_tools/patient_consultation.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/package_tools/patient_documents.dart'; -import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/package_tools/patient_info.dart'; -import 'package:flutter/material.dart'; - -class PatientProfile extends StatefulWidget { - final PatientViewArguments arguments; - const PatientProfile({ - super.key, - required this.arguments, - }); - - @override - State createState() => _PatientProfileState(); -} - -class _PatientProfileState extends State { - int _selcetedIndex = 0; - @override - Widget build(BuildContext context) { - return MihPackage( - appActionButton: getAction(), - appTools: getTools(), - appBody: getToolBody(), - appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); - }, - ); - } - - MihPackageAction getAction() { - return MihPackageAction( - icon: const Icon(Icons.arrow_back), - iconSize: 35, - onTap: () { - if (widget.arguments.type == "business") { - context.pop(); - } else { - context.goNamed( - 'mihHome', - extra: true, - ); - } - FocusScope.of(context).unfocus(); - }, - ); - } - - MihPackageTools getTools() { - Map temp = {}; - temp[const Icon(Icons.perm_identity)] = () { - setState(() { - _selcetedIndex = 0; - }); - }; - temp[const Icon(Icons.article_outlined)] = () { - setState(() { - _selcetedIndex = 1; - }); - }; - temp[const Icon(Icons.file_present)] = () { - setState(() { - _selcetedIndex = 2; - }); - }; - temp[const Icon(Icons.file_open_outlined)] = () { - setState(() { - _selcetedIndex = 3; - }); - }; - return MihPackageTools( - tools: temp, - selcetedIndex: _selcetedIndex, - ); - } - - List getToolBody() { - List toolBodies = [ - PatientInfo( - signedInUser: widget.arguments.signedInUser, - selectedPatient: widget.arguments.selectedPatient!, - type: widget.arguments.type, - ), - PatientConsultation( - patientAppId: widget.arguments.selectedPatient!.app_id, - selectedPatient: widget.arguments.selectedPatient!, - signedInUser: widget.arguments.signedInUser, - business: widget.arguments.business, - businessUser: widget.arguments.businessUser, - type: widget.arguments.type, - ), - PatientDocuments( - patientIndex: widget.arguments.selectedPatient!.idpatients, - selectedPatient: widget.arguments.selectedPatient!, - signedInUser: widget.arguments.signedInUser, - business: widget.arguments.business, - businessUser: widget.arguments.businessUser, - type: widget.arguments.type, - ), - PatientClaimOrStatement( - patientIndex: widget.arguments.selectedPatient!.idpatients, - selectedPatient: widget.arguments.selectedPatient!, - signedInUser: widget.arguments.signedInUser, - business: widget.arguments.business, - businessUser: widget.arguments.businessUser, - type: widget.arguments.type, - ), - ]; - return toolBodies; - } - - List getToolTitle() { - List toolTitles = [ - "Details", - "Notes", - "Documents", - "Claims", - ]; - return toolTitles; - } -} diff --git a/Frontend/lib/mih_packages/test/test.dart b/Frontend/lib/mih_packages/test/test.dart deleted file mode 100644 index af787b72..00000000 --- a/Frontend/lib/mih_packages/test/test.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'package:flutter/material.dart'; - -import '../../mih_components/mih_layout/mih_action.dart'; -import '../../mih_components/mih_layout/mih_body.dart'; -import '../../mih_components/mih_layout/mih_header.dart'; -import '../../mih_components/mih_layout/mih_layout_builder.dart'; - -class MIHTest extends StatefulWidget { - const MIHTest({super.key}); - - @override - State createState() => _MIHTestState(); -} - -class _MIHTestState extends State { - // late YoutubePlayerController videoController; - // String videoLink = "https://www.youtube.com/watch?v=P2bM9eosJ_A"; - // @override - // void initState() { - // videoController = YoutubePlayerController( - // initialVideoId: "P2bM9eosJ_A", - // ); - // super.initState(); - // } - - @override - Widget build(BuildContext context) { - return MIHLayoutBuilder( - actionButton: MIHAction( - icon: const Icon(Icons.arrow_back), - iconSize: 35, - onTap: () { - Navigator.of(context).pushNamedAndRemoveUntil( - '/', - arguments: true, - (route) => false, - ); - }, - ), - header: const MIHHeader( - headerAlignment: MainAxisAlignment.center, - headerItems: [ - Text( - "Test", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 25, - ), - ), - ], - ), - secondaryActionButton: null, - body: const MIHBody( - borderOn: false, - bodyItems: [ - // YoutubePlayer( - // controller: videoController, - // ), - ], - ), - actionDrawer: null, - secondaryActionDrawer: null, - bottomNavBar: null, - pullDownToRefresh: false, - onPullDown: () async {}, - ); - } -} diff --git a/Frontend/lib/mih_services/mih_access_controls_services.dart b/Frontend/lib/mih_services/mih_access_controls_services.dart index 931c4899..322031f9 100644 --- a/Frontend/lib/mih_services/mih_access_controls_services.dart +++ b/Frontend/lib/mih_services/mih_access_controls_services.dart @@ -2,11 +2,131 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart'; +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_providers/mih_access_controlls_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_notification_services.dart'; import 'package:supertokens_flutter/http.dart' as http; class MihAccessControlsServices { + Future getBusinessAccessListOfPatient( + String app_id, + MihAccessControllsProvider mihAccessColtrollsProvider, + ) async { + final response = await http.get(Uri.parse( + "${AppEnviroment.baseApiUrl}/access-requests/personal/patient/$app_id")); + // var errorCode = response.statusCode.toString(); + // print(response.statusCode); + // print(response.body); + + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List patientAccesses = List.from( + l.map((model) => PatientAccess.fromJson(model))); + if (response.statusCode == 200) { + mihAccessColtrollsProvider.setAccessList(patientAccesses); + } + return response.statusCode; + } else { + throw Exception('failed to pull patient access List for business'); + } + } + + /// This function is used to create patient access and trigger notification to patient + /// + /// Patameters:- + /// String business_id, + /// String app_id, + /// String type, + /// String requested_by, + /// BuildContext context, + /// + /// Returns void (triggers notification of success 201). + static Future addPatientAccessAPICall( + String business_id, + String app_id, + String type, + String requested_by, + bool personalSelected, + BusinessArguments args, + BuildContext context, + ) async { + var response = await http.post( + Uri.parse("${AppEnviroment.baseApiUrl}/access-requests/insert/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + // business_id: str + // app_id: str + // type: str + // requested_by: str + body: jsonEncode({ + "business_id": business_id, + "app_id": app_id, + "type": type, + "requested_by": requested_by, + }), + ); + if (response.statusCode == 201) { + await MihNotificationApis.addAccessRequestNotificationAPICall( + app_id, requested_by, personalSelected, args, context); + } else { + internetConnectionPopUp(context); + } + } + + /// This function is used to reapply for access to patient. + /// + /// Patameters:- + /// String business_id, + /// String app_id, + /// BuildContext context, + /// + /// Returns void (on success 200 navigate to /mih-access ). + static Future reapplyPatientAccessAPICall( + String business_id, + String app_id, + bool personalSelected, + BusinessArguments args, + BuildContext context, + ) async { + var response = await http.put( + Uri.parse("${AppEnviroment.baseApiUrl}/access-requests/re-apply/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + // business_id: str + // app_id: str + // status: str + // approved_by: str + body: jsonEncode({ + "business_id": business_id, + "app_id": app_id, + }), + ); + if (response.statusCode == 200) { + await MihNotificationApis.reapplyAccessRequestNotificationAPICall( + app_id, personalSelected, args, context); + //notification here + } else { + internetConnectionPopUp(context); + } + } + + static void internetConnectionPopUp(BuildContext context) { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage( + errorType: "Internet Connection", + ); + }, + ); + } + /// This function is used to UPDATE access the business has. /// /// Patameters:- diff --git a/Frontend/lib/mih_services/mih_business_details_services.dart b/Frontend/lib/mih_services/mih_business_details_services.dart index b59840c1..f12e1282 100644 --- a/Frontend/lib/mih_services/mih_business_details_services.dart +++ b/Frontend/lib/mih_services/mih_business_details_services.dart @@ -1,10 +1,15 @@ import 'dart:convert'; +import 'package:go_router/go_router.dart'; import 'package:http/http.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:provider/provider.dart'; +import 'package:supertokens_flutter/supertokens.dart'; import '../mih_components/mih_pop_up_messages/mih_error_message.dart'; import 'package:supertokens_flutter/http.dart' as http; @@ -75,8 +80,9 @@ class MihBusinessDetailsServices { } Future getBusinessDetailsByUser( - String app_id, + BuildContext context, ) async { + String app_id = await SuperTokens.getUserId(); var response = await http.get( Uri.parse("${AppEnviroment.baseApiUrl}/business/app_id/$app_id"), headers: { @@ -86,7 +92,9 @@ class MihBusinessDetailsServices { if (response.statusCode == 200) { String body = response.body; var jsonBody = jsonDecode(body); - return Business.fromJson(jsonBody); + Business? business = Business.fromJson(jsonBody); + context.read().setBusiness(newBusiness: business); + return business; } else { return null; } @@ -112,7 +120,7 @@ class MihBusinessDetailsServices { } Future createBusinessDetails( - String appId, + MzansiProfileProvider provider, String busineName, String businessType, String businessRegistrationNo, @@ -133,9 +141,6 @@ class MihBusinessDetailsServices { return const Mihloadingcircle(); }, ); - String logoPath = businessLogoFilename.isNotEmpty - ? "$appId/business_files/$businessLogoFilename" - : ""; var response = await http.post( Uri.parse("${AppEnviroment.baseApiUrl}/business/insert/"), headers: { @@ -146,7 +151,7 @@ class MihBusinessDetailsServices { "type": businessType, "registration_no": businessRegistrationNo, "logo_name": businessLogoFilename, - "logo_path": logoPath, + "logo_path": "", "contact_no": businessPhoneNumber, "bus_email": businessEmail, "gps_location": businessLocation, @@ -157,7 +162,50 @@ class MihBusinessDetailsServices { "mission_vision": businessMissionVision, }), ); - Navigator.of(context).pop(); + context.pop(); + if (response.statusCode == 201) { + int finalStatusCode = await updateBusinessDetailsV2( + jsonDecode(response.body)['business_id'], + busineName, + businessType, + businessRegistrationNo, + businessPracticeNo, + businessVatNo, + businessEmail, + businessPhoneNumber, + businessLocation, + businessLogoFilename, + businessWebsite, + businessRating, + businessMissionVision, + provider, + context, + ); + if (finalStatusCode == 200) { + String logoPath = businessLogoFilename.isNotEmpty + ? "${jsonDecode(response.body)['business_id']}/business_files/$businessLogoFilename" + : ""; + provider.setBusiness( + newBusiness: Business( + jsonDecode(response.body)['business_id'], + busineName, + businessType, + businessRegistrationNo, + businessLogoFilename, + logoPath, + businessPhoneNumber, + businessEmail, + provider.user!.app_id, + businessLocation, + businessPracticeNo, + businessVatNo, + businessWebsite, + businessRating, + businessMissionVision, + ), + ); + } + } return response; } @@ -175,6 +223,7 @@ class MihBusinessDetailsServices { String businessWebsite, String businessRating, String businessMissionVision, + MzansiProfileProvider provider, BuildContext context, ) async { showDialog( @@ -183,6 +232,7 @@ class MihBusinessDetailsServices { return const Mihloadingcircle(); }, ); + var filePath = "$business_id/business_files/$business_logo_name"; var response = await http.put( Uri.parse("${AppEnviroment.baseApiUrl}/business/update/v2/"), headers: { @@ -194,7 +244,7 @@ class MihBusinessDetailsServices { "type": business_type, "registration_no": business_registration_no, "logo_name": business_logo_name, - "logo_path": "$business_id/business_files/$business_logo_name", + "logo_path": filePath, "contact_no": business_phone_number, "bus_email": business_email, "gps_location": business_location, @@ -205,8 +255,29 @@ class MihBusinessDetailsServices { "mission_vision": businessMissionVision, }), ); - Navigator.of(context).pop(); + context.pop(); if (response.statusCode == 200) { + provider.setBusiness( + newBusiness: Business( + business_id, + business_name, + business_type, + business_registration_no, + business_logo_name, + filePath, + business_phone_number, + business_email, + business_id, + business_location, + business_practice_no, + business_vat_no, + businessWebsite, + businessRating, + businessMissionVision, + ), + ); + String newProPicUrl = await MihFileApi.getMinioFileUrl(filePath, context); + provider.setBusinessProfilePicUrl(newProPicUrl); return 200; } else { return 500; diff --git a/Frontend/lib/mih_services/mih_business_employee_services.dart b/Frontend/lib/mih_services/mih_business_employee_services.dart new file mode 100644 index 00000000..4518437b --- /dev/null +++ b/Frontend/lib/mih_services/mih_business_employee_services.dart @@ -0,0 +1,142 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:supertokens_flutter/http.dart' as http; + +class MihBusinessEmployeeServices { + Future fetchEmployees( + MzansiProfileProvider mzansiProfileProvider, BuildContext context) async { + final response = await http.get(Uri.parse( + "${AppEnviroment.baseApiUrl}/business-user/employees/${mzansiProfileProvider.businessUser!.business_id}")); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List employeeList = List.from( + l.map((model) => BusinessEmployee.fromJson(model))); + mzansiProfileProvider.setEmployeeList(employeeList: employeeList); + } else { + throw Exception('failed to load employees'); + } + return response.statusCode; + } + + Future addEmployee( + MzansiProfileProvider provider, + AppUser newEmployee, + String access, + BuildContext context, + ) async { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle(); + }, + ); + var response = await http.post( + Uri.parse("${AppEnviroment.baseApiUrl}/business-user/insert/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "business_id": provider.business!.business_id, + "app_id": newEmployee.app_id, + "signature": "", + "sig_path": "", + "title": "", + "access": access, + }), + ); + if (response.statusCode == 201) { + provider.addEmployee( + newEmployee: BusinessEmployee( + provider.business!.business_id, + newEmployee.app_id, + "", + access, + newEmployee.fname, + newEmployee.lname, + newEmployee.email, + newEmployee.username, + ), + ); + provider.setBusinessIndex(2); + } + context.pop(); + return response.statusCode; + } + + Future updateEmployeeDetails( + MzansiProfileProvider provider, + BusinessEmployee employee, + String newTitle, + String newAccess, + BuildContext context) async { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle(); + }, + ); + var response = await http.put( + Uri.parse("${AppEnviroment.baseApiUrl}/business-user/employees/update/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "business_id": employee.business_id, + "app_id": employee.app_id, + "title": newTitle, + "access": newAccess, + }), + ); + if (response.statusCode == 200) { + provider.updateEmplyeeDetails( + updatedEmployee: BusinessEmployee( + employee.business_id, + employee.app_id, + newTitle, + newAccess, + employee.fname, + employee.lname, + employee.email, + employee.username, + ), + ); + } + context.pop(); + return response.statusCode; + } + + Future deleteEmployee( + MzansiProfileProvider provider, + BusinessEmployee employee, + BuildContext context, + ) async { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle(); + }, + ); + var response = await http.delete( + Uri.parse("${AppEnviroment.baseApiUrl}/business-user/employees/delete/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "business_id": employee.business_id, + "app_id": employee.app_id, + }), + ); + if (response.statusCode == 200) { + provider.deleteEmplyee(deletedEmployee: employee); + } + context.pop(); + return response.statusCode; + } +} diff --git a/Frontend/lib/mih_services/mih_claim_statement_generation_services.dart b/Frontend/lib/mih_services/mih_claim_statement_generation_services.dart index b26edd99..7cb073bd 100644 --- a/Frontend/lib/mih_services/mih_claim_statement_generation_services.dart +++ b/Frontend/lib/mih_services/mih_claim_statement_generation_services.dart @@ -5,6 +5,8 @@ import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loa import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/claim_statement_file.dart'; import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:supertokens_flutter/http.dart' as http; import '../mih_components/mih_pop_up_messages/mih_error_message.dart'; @@ -20,8 +22,9 @@ class MIHClaimStatementGenerationApi { /// /// Returns TBC. Future generateClaimStatement( + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, ClaimStatementGenerationArguments data, - PatientViewArguments args, String env, BuildContext context, ) async { @@ -84,19 +87,13 @@ class MIHClaimStatementGenerationApi { }, body: jsonEncode({ "app_id": data.patient_app_id, - "business_id": args.business!.business_id, + "business_id": profileProvider.business!.business_id, "file_path": "${data.patient_app_id}/claims-statements/$fileName", "file_name": fileName }), ); if (response2.statusCode == 201) { - context.pop(); // end loading circle - context.pop(); - - context.pushNamed( - 'patientManagerPatient', - extra: args, - ); + getClaimStatementFilesByPatient(patientManagerProvider); String message = "The ${data.document_type}: $fileName has been successfully generated and added to ${data.patient_full_name}'s record. You can now access and download it for their use."; successPopUp(message, context); @@ -114,11 +111,11 @@ class MIHClaimStatementGenerationApi { /// /// Returns List. static Future> getClaimStatementFilesByPatient( - String app_id, + PatientManagerProvider patientManagerProvider, ) async { //print("Patien manager page: $endpoint"); final response = await http.get(Uri.parse( - "${AppEnviroment.baseApiUrl}/files/claim-statement/patient/$app_id")); + "${AppEnviroment.baseApiUrl}/files/claim-statement/patient/${patientManagerProvider.selectedPatient!.app_id}")); // print("Here"); // print("Body: ${response.body}"); // print("Code: ${response.statusCode}"); @@ -132,7 +129,8 @@ class MIHClaimStatementGenerationApi { List docList = List.from( l.map((model) => ClaimStatementFile.fromJson(model))); //print("Here3"); - //print(patientQueue); + patientManagerProvider.setClaimsDocuments( + patientClaimsDocuments: docList); return docList; } else { throw Exception( diff --git a/Frontend/lib/mih_services/mih_currency_exchange_rate_services.dart b/Frontend/lib/mih_services/mih_currency_exchange_rate_services.dart index 2be8748e..02f5bd35 100644 --- a/Frontend/lib/mih_services/mih_currency_exchange_rate_services.dart +++ b/Frontend/lib/mih_services/mih_currency_exchange_rate_services.dart @@ -1,6 +1,9 @@ import 'dart:convert'; +import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/currency.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calculator_provider.dart'; +import 'package:provider/provider.dart'; import 'package:supertokens_flutter/http.dart' as http; class MihCurrencyExchangeRateServices { @@ -21,7 +24,7 @@ class MihCurrencyExchangeRateServices { } } - static Future> getCurrencyCodeList() async { + static Future getCurrencyCodeList(BuildContext context) async { final response = await http.get(Uri.parse( "https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies.min.json")); if (response.statusCode == 200) { @@ -32,7 +35,11 @@ class MihCurrencyExchangeRateServices { currencies.add("$code - $name"); }); currencies.sort(); - return currencies; + if (response.statusCode == 200) { + context + .read() + .setAvailableCurrencies(currencies: currencies); + } } else { throw Exception('failed to fatch currencies'); } diff --git a/Frontend/lib/mih_services/mih_file_services.dart b/Frontend/lib/mih_services/mih_file_services.dart index fa983869..e3eec301 100644 --- a/Frontend/lib/mih_services/mih_file_services.dart +++ b/Frontend/lib/mih_services/mih_file_services.dart @@ -1,6 +1,8 @@ import 'dart:convert'; import 'package:file_picker/file_picker.dart'; +import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.dart'; 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'; @@ -43,8 +45,9 @@ class MihFileApi { fileUrl = decodedData['minioURL']; } else { // internetConnectionPopUp(context); - print("Error: ${response.statusCode}"); - print("Error: ${response.body}"); + KenLogger.error("Get File Error: $url"); + KenLogger.error("Get File Error: ${response.statusCode}"); + KenLogger.error("Get File Error: ${response.body}"); } } catch (e) { // internetConnectionPopUp(context); @@ -75,7 +78,7 @@ class MihFileApi { request.files.add(await http2.MultipartFile.fromBytes('file', file!.bytes!, filename: file.name.replaceAll(RegExp(r' '), '-'))); var response = await request.send(); - Navigator.of(context).pop(); // Pop loading dialog + context.pop(); // Pop loading dialog return response.statusCode; } @@ -99,7 +102,7 @@ class MihFileApi { "env": env, }), ); - Navigator.of(context).pop(); // Pop loading dialog + context.pop(); // Pop loading dialog return response.statusCode; } diff --git a/Frontend/lib/mih_services/mih_minesweeper_services.dart b/Frontend/lib/mih_services/mih_minesweeper_services.dart new file mode 100644 index 00000000..6d5eb524 --- /dev/null +++ b/Frontend/lib/mih_services/mih_minesweeper_services.dart @@ -0,0 +1,80 @@ +import 'dart:convert'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/minesweeper_player_score.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:supertokens_flutter/http.dart' as http; + +class MihMinesweeperServices { + Future getTop20Leaderboard( + MihMineSweeperProvider mineSweeperProvider, + ) async { + String difficulty = mineSweeperProvider.difficulty; + var response = await http.get( + Uri.parse( + "${AppEnviroment.baseApiUrl}/minesweeper/leaderboard/top20/$difficulty"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + ); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List leaderboard = + List.from( + l.map((model) => MinesweeperPlayerScore.fromJson(model))); + mineSweeperProvider.setLeaderboard(leaderboard: leaderboard); + } else { + mineSweeperProvider.setLeaderboard(leaderboard: null); + } + return response.statusCode; + } + + Future getMyScoreboard( + MzansiProfileProvider profileProvider, + MihMineSweeperProvider mineSweeperProvider, + ) async { + String difficulty = mineSweeperProvider.difficulty; + var response = await http.get( + Uri.parse( + "${AppEnviroment.baseApiUrl}/minesweeper/leaderboard/top_score/$difficulty/${profileProvider.user!.app_id}"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + ); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List leaderboard = + List.from( + l.map((model) => MinesweeperPlayerScore.fromJson(model))); + mineSweeperProvider.setMyScoreboard(myScoreboard: leaderboard); + } else { + mineSweeperProvider.setMyScoreboard(myScoreboard: null); + } + return response.statusCode; + } + + Future addPlayerScore( + MzansiProfileProvider profileProvider, + MihMineSweeperProvider mineSweeperProvider, + String game_time, + double game_score, + ) async { + DateTime now = DateTime.now(); + String formattedDateTime = now.toString(); + var response = await http.post( + Uri.parse( + "${AppEnviroment.baseApiUrl}/minesweeper/leaderboard/player_score/insert/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "app_id": profileProvider.user!.app_id, + "difficulty": mineSweeperProvider.difficulty, + "game_time": game_time, + "game_score": game_score, + "played_date": formattedDateTime, + }), + ); + return response.statusCode; + } +} diff --git a/Frontend/lib/mih_services/mih_my_business_user_services.dart b/Frontend/lib/mih_services/mih_my_business_user_services.dart index e1481493..bb927b5f 100644 --- a/Frontend/lib/mih_services/mih_my_business_user_services.dart +++ b/Frontend/lib/mih_services/mih_my_business_user_services.dart @@ -1,15 +1,21 @@ import 'dart:convert'; +import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:provider/provider.dart'; +import 'package:supertokens_flutter/supertokens.dart'; import '../mih_components/mih_pop_up_messages/mih_error_message.dart'; import 'package:supertokens_flutter/http.dart' as http; class MihMyBusinessUserServices { Future getBusinessUser( - String app_id, + BuildContext context, ) async { + String app_id = await SuperTokens.getUserId(); var response = await http.get( Uri.parse("${AppEnviroment.baseApiUrl}/business-user/$app_id"), headers: { @@ -17,7 +23,13 @@ class MihMyBusinessUserServices { }, ); if (response.statusCode == 200) { - return BusinessUser.fromJson(jsonDecode(response.body)); + // KenLogger.success(response.body); + BusinessUser? businessUser = + BusinessUser.fromJson(jsonDecode(response.body)); + context + .read() + .setBusinessUser(newBusinessUser: businessUser); + return businessUser; } else { return null; } @@ -29,6 +41,7 @@ class MihMyBusinessUserServices { String signatureFilename, String title, String access, + MzansiProfileProvider provider, BuildContext context, ) async { showDialog( @@ -37,6 +50,7 @@ class MihMyBusinessUserServices { return const Mihloadingcircle(); }, ); + String sigPath = "$business_id/business_files/$signatureFilename"; var response = await http.post( Uri.parse("${AppEnviroment.baseApiUrl}/business-user/insert/"), headers: { @@ -46,13 +60,17 @@ class MihMyBusinessUserServices { "business_id": business_id, "app_id": app_id, "signature": signatureFilename, - "sig_path": "$business_id/business_files/$signatureFilename", + "sig_path": sigPath, "title": title, "access": access, }), ); - Navigator.of(context).pop(); + context.pop(); if (response.statusCode == 201) { + provider.setBusinessUser( + newBusinessUser: BusinessUser( + 0, business_id, app_id, signatureFilename, sigPath, title, access), + ); return 201; } else { internetConnectionPopUp(context); @@ -67,6 +85,7 @@ class MihMyBusinessUserServices { String bUserTitle, String bUserAccess, String signatureFileName, + MzansiProfileProvider provider, BuildContext context, ) async { showDialog( @@ -75,6 +94,7 @@ class MihMyBusinessUserServices { return const Mihloadingcircle(); }, ); + var filePath = "$app_id/business_files/$signatureFileName"; var response = await http.put( Uri.parse("${AppEnviroment.baseApiUrl}/business-user/update/"), headers: { @@ -84,32 +104,26 @@ class MihMyBusinessUserServices { "business_id": business_id, "app_id": app_id, "signature": signatureFileName, - "sig_path": "$app_id/business_files/$signatureFileName", + "sig_path": filePath, "title": bUserTitle, "access": bUserAccess, }), ); - // var response = await http.put( - // Uri.parse("${AppEnviroment.baseApiUrl}/business/update/"), - // headers: { - // "Content-Type": "application/json; charset=UTF-8" - // }, - // body: jsonEncode({ - // "business_id": business_id, - // "Name": business_name, - // "type": business_type, - // "registration_no": business_registration_no, - // "logo_name": business_logo_name, - // "logo_path": "$business_id/business_files/$business_logo_name", - // "contact_no": business_phone_number, - // "bus_email": business_email, - // "gps_location": business_location, - // "practice_no": business_practice_no, - // "vat_no": business_vat_no, - // }), - // ); - Navigator.of(context).pop(); + context.pop(); if (response.statusCode == 200) { + provider.setBusinessUser( + newBusinessUser: BusinessUser( + provider.businessUser!.idbusiness_users, + business_id, + app_id, + signatureFileName, + filePath, + bUserTitle, + bUserAccess, + ), + ); + String newProPicUrl = await MihFileApi.getMinioFileUrl(filePath, context); + provider.setBusinessUserSignatureUrl(newProPicUrl); return 200; } else { internetConnectionPopUp(context); diff --git a/Frontend/lib/mih_services/mih_mzansi_calendar_services.dart b/Frontend/lib/mih_services/mih_mzansi_calendar_services.dart index d01785aa..6c18fb47 100644 --- a/Frontend/lib/mih_services/mih_mzansi_calendar_services.dart +++ b/Frontend/lib/mih_services/mih_mzansi_calendar_services.dart @@ -4,10 +4,10 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/appointment.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.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'; @@ -23,9 +23,10 @@ class MihMzansiCalendarApis { /// date (yyyy-mm-dd), /// /// Returns Future>. - static Future> getPersonalAppointments( + static Future getPersonalAppointments( String app_id, String date, + MihCalendarProvider mihCalendarProvider, ) async { final response = await http.get(Uri.parse( "${AppEnviroment.baseApiUrl}/appointments/personal/$app_id?date=$date")); @@ -33,7 +34,9 @@ class MihMzansiCalendarApis { Iterable l = jsonDecode(response.body); List personalAppointments = List.from(l.map((model) => Appointment.fromJson(model))); - return personalAppointments; + mihCalendarProvider.setPersonalAppointments( + appointments: personalAppointments); + return response.statusCode; } else { throw Exception('failed to fatch personal appointments'); } @@ -46,38 +49,21 @@ class MihMzansiCalendarApis { /// date (yyyy-mm-dd), /// /// Returns Future>. - static Future> getBusinessAppointments( + static Future getBusinessAppointments( String business_id, bool waitingRoom, String date, + MihCalendarProvider mihCalendarProvider, ) async { - //print("Patien manager page: $endpoint"); final response = await http.get(Uri.parse( "${AppEnviroment.baseApiUrl}/appointments/business/$business_id?date=$date")); - // 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 businessAppointments = List.from(l.map((model) => Appointment.fromJson(model))); - //print("Here3"); - //print(patientQueue); - // if (waitingRoom == true) { - // businessAppointments = businessAppointments - // .where((element) => element.app_id != "") - // .toList(); - // } else { - // businessAppointments = businessAppointments - // .where((element) => element.app_id == "") - // .toList(); - // } - return businessAppointments; + mihCalendarProvider.setBusinessAppointments( + appointments: businessAppointments); + return response.statusCode; } else { throw Exception('failed to fatch business appointments'); } @@ -98,6 +84,7 @@ class MihMzansiCalendarApis { BusinessUser? businessUser, bool inWaitingRoom, int idappointments, + MihCalendarProvider mihCalendarProvider, BuildContext context, ) async { loadingPopUp(context); @@ -109,6 +96,19 @@ class MihMzansiCalendarApis { body: jsonEncode({"idappointments": idappointments}), ); context.pop(); + if (response.statusCode == 200) { + if (personalSelected == true) { + mihCalendarProvider.deletePersonalAppointment( + appointmentId: idappointments); + getPersonalAppointments(signedInUser.app_id, + mihCalendarProvider.selectedDay, mihCalendarProvider); + } else { + mihCalendarProvider.deleteBusinessAppointment( + appointmentId: idappointments); + getBusinessAppointments(business!.business_id, inWaitingRoom, + mihCalendarProvider.selectedDay, mihCalendarProvider); + } + } return response.statusCode; //print("Here4"); //print(response.statusCode); @@ -163,6 +163,7 @@ class MihMzansiCalendarApis { String description, String date, String time, + MihCalendarProvider mihCalendarProvider, BuildContext context, ) async { loadingPopUp(context); @@ -181,6 +182,18 @@ class MihMzansiCalendarApis { }), ); context.pop(); + if (response.statusCode == 201) { + mihCalendarProvider.addPersonalAppointment( + newAppointment: Appointment( + idappointments: 0, + app_id: signedInUser.app_id, + business_id: "", + date_time: "$date $time", + title: title, + description: description, + ), + ); + } return response.statusCode; // if (response.statusCode == 201) { // Navigator.pop(context); @@ -227,6 +240,7 @@ class MihMzansiCalendarApis { String description, String date, String time, + MihCalendarProvider mihCalendarProvider, BuildContext context, ) async { loadingPopUp(context); @@ -245,43 +259,19 @@ class MihMzansiCalendarApis { }), ); context.pop(); + if (response.statusCode == 201) { + mihCalendarProvider.addBusinessAppointment( + newAppointment: Appointment( + idappointments: 0, + app_id: "", + business_id: business.business_id, + date_time: "$date $time", + title: title, + description: description, + ), + ); + } return response.statusCode; - // if (response.statusCode == 201) { - // // Navigator.pop(context); - // Navigator.pop(context); - // Navigator.pop(context); - // Navigator.pop(context); - // String message = - // "Your appointment \"$title\" for the $date $title has been deleted."; - - // // Navigator.pop(context); - // if (inWaitingRoom) { - // Navigator.of(context).pushNamed( - // '/patient-manager', - // arguments: PatManagerArguments( - // signedInUser, - // false, - // business, - // businessUser, - // ), - // ); - // } else { - // Navigator.of(context).pushNamed( - // '/calendar', - // arguments: CalendarArguments( - // signedInUser, - // false, - // business, - // businessUser, - // ), - // ); - // } - - // successPopUp(message, context); - // } else { - // Navigator.pop(context); - // internetConnectionPopUp(context); - // } } /// This function is used to add an appointment to users mzansi Calendar. @@ -300,7 +290,7 @@ class MihMzansiCalendarApis { AppUser signedInUser, bool personalSelected, String patientAppId, - BusinessArguments businessArgs, + String businessId, String title, String description, String date, @@ -315,7 +305,7 @@ class MihMzansiCalendarApis { }, body: jsonEncode({ "app_id": patientAppId, - "business_id": businessArgs.business?.business_id, + "business_id": businessId, "title": title, "description": description, "date": date, @@ -324,20 +314,6 @@ class MihMzansiCalendarApis { ); context.pop(); return response.statusCode; - // if (response.statusCode == 201) { - // MihNotificationApis.addNewAppointmentNotificationAPICall( - // patientAppId, - // personalSelected, - // date, - // time, - // businessArgs, - // context, - // ); - // // Navigator.pop(context); - // } else { - // Navigator.pop(context); - // internetConnectionPopUp(context); - // } } /// This function is used to update an appointment to users mzansi Calendar. @@ -362,6 +338,7 @@ class MihMzansiCalendarApis { String description, String date, String time, + MihCalendarProvider mihCalendarProvider, BuildContext context, ) async { loadingPopUp(context); @@ -379,6 +356,18 @@ class MihMzansiCalendarApis { }), ); context.pop(); + if (response.statusCode == 200) { + mihCalendarProvider.editPersonalAppointment( + updatedAppointment: Appointment( + idappointments: idappointments, + app_id: signedInUser.app_id, + business_id: "", + date_time: "$date $time", + title: title, + description: description, + ), + ); + } return response.statusCode; // if (response.statusCode == 200) { // Navigator.pop(context); @@ -426,6 +415,7 @@ class MihMzansiCalendarApis { String description, String date, String time, + MihCalendarProvider mihCalendarProvider, BuildContext context, ) async { loadingPopUp(context); @@ -443,6 +433,18 @@ class MihMzansiCalendarApis { }), ); context.pop(); + if (response.statusCode == 200) { + mihCalendarProvider.editBusinessAppointment( + updatedAppointment: Appointment( + idappointments: idappointments, + app_id: "", + business_id: business!.business_id, + date_time: "$date $time", + title: title, + description: description, + ), + ); + } return response.statusCode; // if (response.statusCode == 200) { // Navigator.pop(context); diff --git a/Frontend/lib/mih_services/mih_mzansi_directory_services.dart b/Frontend/lib/mih_services/mih_mzansi_directory_services.dart index 18c6af8c..322615de 100644 --- a/Frontend/lib/mih_services/mih_mzansi_directory_services.dart +++ b/Frontend/lib/mih_services/mih_mzansi_directory_services.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_review.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:supertokens_flutter/http.dart' as http; @@ -156,14 +157,17 @@ class MihMzansiDirectoryServices { Future> getAllUserBookmarkedBusiness( String app_id, + MzansiDirectoryProvider directoryProvider, ) async { final response = await http.get(Uri.parse( "${AppEnviroment.baseApiUrl}/mzansi-directory/bookmarked-business/user/all/$app_id/")); if (response.statusCode == 200) { Iterable l = jsonDecode(response.body); - List businessReviews = List.from( - l.map((model) => BookmarkedBusiness.fromJson(model))); - return businessReviews; + List favouriteBusinesses = + List.from( + l.map((model) => BookmarkedBusiness.fromJson(model))); + directoryProvider.setFavouriteBusinesses(businesses: favouriteBusinesses); + return favouriteBusinesses; } else if (response.statusCode == 404) { return []; } else { diff --git a/Frontend/lib/mih_services/mih_mzansi_wallet_services.dart b/Frontend/lib/mih_services/mih_mzansi_wallet_services.dart index 01254196..7dcdd4e1 100644 --- a/Frontend/lib/mih_services/mih_mzansi_wallet_services.dart +++ b/Frontend/lib/mih_services/mih_mzansi_wallet_services.dart @@ -5,6 +5,8 @@ import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/loyalty_card.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_wallet_provider.dart'; +import 'package:provider/provider.dart'; import 'package:supertokens_flutter/http.dart' as http; import '../mih_components/mih_pop_up_messages/mih_error_message.dart'; @@ -14,45 +16,39 @@ import '../mih_config/mih_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( + static Future getLoyaltyCards( String app_id, + BuildContext context, ) async { final response = await http.get(Uri.parse( "${AppEnviroment.baseApiUrl}/mzasni-wallet/loyalty-cards/$app_id")); if (response.statusCode == 200) { Iterable l = jsonDecode(response.body); - List patientQueue = List.from( + List myCards = List.from( l.map((model) => MIHLoyaltyCard.fromJson(model))); - return patientQueue; + context.read().setLoyaltyCards(cards: myCards); + // return myCards; } else { throw Exception('failed to fatch loyalty cards'); } } - /// This function is used to fetch a list of loyalty cards for a user. - /// - /// Patameters: app_id . - /// - /// Returns List. - static Future> getFavouriteLoyaltyCards( + static Future getFavouriteLoyaltyCards( String app_id, + BuildContext context, ) async { //print("Patien manager page: $endpoint"); final response = await http.get(Uri.parse( "${AppEnviroment.baseApiUrl}/mzasni-wallet/loyalty-cards/favourites/$app_id")); if (response.statusCode == 200) { Iterable l = jsonDecode(response.body); - List patientQueue = List.from( + List myCards = List.from( l.map((model) => MIHLoyaltyCard.fromJson(model))); - return patientQueue; - } else { - throw Exception('failed to fatch loyalty cards'); + context.read().setFavouriteCards(cards: myCards); } + // else { + // throw Exception('failed to fatch loyalty cards'); + // } } /// This function is used to Delete loyalty card from users mzansi wallet. @@ -80,6 +76,11 @@ class MIHMzansiWalletApis { //print("Here4"); //print(response.statusCode); context.pop(); + if (response.statusCode == 200) { + context + .read() + .deleteLoyaltyCard(cardId: idloyalty_cards); + } return response.statusCode; // if (response.statusCode == 200) { // Navigator.of(context).pop(); @@ -165,6 +166,7 @@ class MIHMzansiWalletApis { static Future updateLoyaltyCardAPICall( AppUser signedInUser, int idloyalty_cards, + String shopName, String favourite, int priority_index, String nickname, @@ -187,6 +189,19 @@ class MIHMzansiWalletApis { }), ); context.pop(); + if (response.statusCode == 200) { + context.read().editLoyaltyCard( + updatedCard: MIHLoyaltyCard( + idloyalty_cards: idloyalty_cards, + app_id: signedInUser.app_id, + shop_name: shopName, + card_number: card_number, + favourite: favourite, + priority_index: priority_index, + nickname: nickname, + ), + ); + } return response.statusCode; } diff --git a/Frontend/lib/mih_services/mih_patient_services.dart b/Frontend/lib/mih_services/mih_patient_services.dart index 57420896..a4b26c4d 100644 --- a/Frontend/lib/mih_services/mih_patient_services.dart +++ b/Frontend/lib/mih_services/mih_patient_services.dart @@ -1,7 +1,12 @@ import 'dart:convert'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/files.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/notes.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:supertokens_flutter/http.dart' as http; @@ -10,6 +15,7 @@ class MihPatientServices { Future getPatientDetails( String appId, + PatientManagerProvider patientManagerProvider, ) async { var response = await http.get( Uri.parse("${AppEnviroment.baseApiUrl}/patients/$appId"), @@ -20,12 +26,32 @@ class MihPatientServices { if (response.statusCode == 200) { String body = response.body; var jsonBody = jsonDecode(body); - return Patient.fromJson(jsonBody); + Patient patient = Patient.fromJson(jsonBody); + patientManagerProvider.setSelectedPatient(selectedPatient: patient); + return patient; } else { return null; } } + static Future> searchPatients( + PatientManagerProvider patientManagerProvider, + String search, + ) async { + final response = await http + .get(Uri.parse("${AppEnviroment.baseApiUrl}/patients/search/$search")); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List patients = + List.from(l.map((model) => Patient.fromJson(model))); + patientManagerProvider.setPatientSearchResults( + patientSearchResults: patients); + return patients; + } else { + throw Exception('failed to load patients'); + } + } + Future addPatientService( String id_no, String fname, @@ -39,7 +65,8 @@ class MihPatientServices { String medName, String medScheme, String address, - AppUser signedInUser, + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, ) async { var response = await http.post( Uri.parse("$baseAPI/patients/insert/"), @@ -59,9 +86,31 @@ class MihPatientServices { "medical_aid_name": medName, "medical_aid_scheme": medScheme, "address": address, - "app_id": signedInUser.app_id, + "app_id": profileProvider.user!.app_id, }), ); + if (response.statusCode == 201) { + await getPatientDetails( + profileProvider.user!.app_id, patientManagerProvider); + // patientManagerProvider.setSelectedPatient( + // selectedPatient: Patient( + // idpatients: 0, + // id_no: id_no, + // first_name: fname, + // last_name: lname, + // email: email, + // cell_no: cell, + // medical_aid: medAid, + // medical_aid_name: medName, + // medical_aid_no: medNo, + // medical_aid_main_member: medMainMem, + // medical_aid_code: medAidCode, + // medical_aid_scheme: medScheme, + // address: address, + // app_id: profileProvider.user!.app_id, + // ), + // ); + } return response.statusCode; } @@ -79,6 +128,7 @@ class MihPatientServices { String medName, String medScheme, String address, + PatientManagerProvider patientManagerProvider, ) async { var response = await http.put( Uri.parse("$baseAPI/patients/update/"), @@ -101,6 +151,176 @@ class MihPatientServices { "app_id": app_id, }), ); + if (response.statusCode == 200) { + await getPatientDetails(app_id, patientManagerProvider); + } return response.statusCode; } + + Future getPatientConsultationNotes( + PatientManagerProvider patientManagerProvider) async { + final response = await http.get(Uri.parse( + "${AppEnviroment.baseApiUrl}/notes/patients/${patientManagerProvider.selectedPatient!.app_id}")); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List notes = + List.from(l.map((model) => Note.fromJson(model))); + patientManagerProvider.setConsultationNotes(consultationNotes: notes); + } + return response.statusCode; + } + + Future addPatientNoteAPICall( + String title, + String noteText, + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + ) async { + var response = await http.post( + Uri.parse("${AppEnviroment.baseApiUrl}/notes/insert/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "note_name": title, + "note_text": noteText, + "doc_office": profileProvider.business!.Name, + "doctor": + "${profileProvider.user!.fname} ${profileProvider.user!.lname}", + "app_id": patientManagerProvider.selectedPatient!.app_id, + }), + ); + if (response.statusCode == 201) { + await getPatientConsultationNotes(patientManagerProvider); + } + return response.statusCode; + } + + Future deletePatientConsultaionNote( + int NoteId, + PatientManagerProvider patientManagerProvider, + ) async { + var response = await http.delete( + Uri.parse("$baseAPI/notes/delete/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({"idpatient_notes": NoteId}), + ); + if (response.statusCode == 201) { + await getPatientConsultationNotes(patientManagerProvider); + } + return response.statusCode; + } + + Future getPatientDocuments( + PatientManagerProvider patientManagerProvider) async { + final response = await http.get(Uri.parse( + "${AppEnviroment.baseApiUrl}/patient_files/get/${patientManagerProvider.selectedPatient!.app_id}")); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List patientDocuments = + List.from(l.map((model) => PFile.fromJson(model))); + patientManagerProvider.setPatientDocuments( + patientDocuments: patientDocuments); + } + return response.statusCode; + } + + Future addPatientFile( + PlatformFile? file, + PatientManagerProvider patientManagerProvider, + ) async { + var fname = file!.name.replaceAll(RegExp(r' '), '-'); + var filePath = + "${patientManagerProvider.selectedPatient!.app_id}/patient_files/$fname"; + var response = await http.post( + Uri.parse("${AppEnviroment.baseApiUrl}/patient_files/insert/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "file_path": filePath, + "file_name": fname, + "app_id": patientManagerProvider.selectedPatient!.app_id + }), + ); + if (response.statusCode == 201) { + await getPatientDocuments(patientManagerProvider); + } + return response.statusCode; + } + + Future generateMedicalCertificate( + String startDate, + String endDate, + String returnDate, + MzansiProfileProvider profileProvider, + PatientManagerProvider patientManagerProvider, + ) async { + DateTime now = DateTime.now(); + String fileName = + "Med-Cert-${patientManagerProvider.selectedPatient!.first_name} ${patientManagerProvider.selectedPatient!.last_name}-${now.toString().substring(0, 19)}.pdf" + .replaceAll(RegExp(r' '), '-'); + var response = await http.post( + Uri.parse("${AppEnviroment.baseApiUrl}/minio/generate/med-cert/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "app_id": patientManagerProvider.selectedPatient!.app_id, + "env": AppEnviroment.getEnv(), + "patient_full_name": + "${patientManagerProvider.selectedPatient!.first_name} ${patientManagerProvider.selectedPatient!.last_name}", + "fileName": fileName, + "id_no": patientManagerProvider.selectedPatient!.id_no, + "docfname": + "DR. ${profileProvider.user!.fname} ${profileProvider.user!.lname}", + "startDate": startDate, + "busName": profileProvider.business!.Name, + "busAddr": "*TO BE ADDED IN THE FUTURE*", + "busNo": profileProvider.business!.contact_no, + "busEmail": profileProvider.business!.bus_email, + "endDate": endDate, + "returnDate": returnDate, + "logo_path": profileProvider.business!.logo_path, + "sig_path": profileProvider.businessUser!.sig_path, + }), + ); + if (response.statusCode == 200) { + var responseAddFiletoDB = await http.post( + Uri.parse("${AppEnviroment.baseApiUrl}/patient_files/insert/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "file_path": + "${patientManagerProvider.selectedPatient!.app_id}/patient_files/$fileName", + "file_name": fileName, + "app_id": patientManagerProvider.selectedPatient!.app_id + }), + ); + if (responseAddFiletoDB.statusCode == 201) { + await getPatientDocuments(patientManagerProvider); + } + } + return response.statusCode; + } + + Future> getPatientAccessListOfBusiness( + PatientManagerProvider patientManagerProvider, + String business_id, + ) async { + final response = await http.get(Uri.parse( + "${AppEnviroment.baseApiUrl}/access-requests/business/patient/$business_id")); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List patientAccesses = List.from( + l.map((model) => PatientAccess.fromJson(model))); + patientManagerProvider.setMyPatientList(myPaitentList: patientAccesses); + return patientAccesses; + } else { + throw Exception('failed to pull patient access List for business'); + } + } } diff --git a/Frontend/lib/mih_services/mih_service_calls.dart b/Frontend/lib/mih_services/mih_service_calls.dart index 411ec8c7..d0de0899 100644 --- a/Frontend/lib/mih_services/mih_service_calls.dart +++ b/Frontend/lib/mih_services/mih_service_calls.dart @@ -1,26 +1,12 @@ import 'dart:convert'; - import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_my_business_user_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_notification_services.dart'; import 'package:flutter/material.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_patient_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_user_services.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/mih_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/supertokens.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_config/mih_env.dart'; @@ -61,7 +47,7 @@ class MIHApiCalls { // Get Userdata var uid = await SuperTokens.getUserId(); - AppUser? user = await MihUserServices().getUserDetails(uid, context); + AppUser? user = await MihUserServices().getUserDetails(context); if (user != null) { userData = user; } else { @@ -70,7 +56,7 @@ class MIHApiCalls { // Get BusinessUserdata BusinessUser? businessUser = - await MihMyBusinessUserServices().getBusinessUser(uid); + await MihMyBusinessUserServices().getBusinessUser(context); if (businessUser != null) { bUserData = businessUser; } else { @@ -79,9 +65,7 @@ class MIHApiCalls { // Get Businessdata Business? business = - await MihBusinessDetailsServices().getBusinessDetailsByUser( - uid, - ); + await MihBusinessDetailsServices().getBusinessDetailsByUser(context); if (business != null) { busData = business; } else { @@ -103,14 +87,14 @@ class MIHApiCalls { ); //get patient profile - Patient? patient = await MihPatientServices().getPatientDetails( - uid, - ); - if (patient != null) { - patientData = patient; - } else { - patientData = null; - } + // Patient? patient = await MihPatientServices().getPatientDetails( + // uid, + // ); + // if (patient != null) { + // patientData = patient; + // } else { + // patientData = null; + // } return HomeArguments( userData, bUserData, busData, patientData, notifi, userPic); @@ -142,52 +126,6 @@ class MIHApiCalls { } } - /// This function is used to get list of access the business has. - /// - /// Patameters: String business_id. - /// - /// Returns List (List of access that match the above parameters). - static Future> getPatientAccessListOfBusiness( - String business_id) async { - final response = await http.get(Uri.parse( - "${AppEnviroment.baseApiUrl}/access-requests/business/patient/$business_id")); - // var errorCode = response.statusCode.toString(); - // print(response.statusCode); - // print(response.body); - - if (response.statusCode == 200) { - Iterable l = jsonDecode(response.body); - List patientAccesses = List.from( - l.map((model) => PatientAccess.fromJson(model))); - return patientAccesses; - } else { - throw Exception('failed to pull patient access List for business'); - } - } - - /// This function is used to get list of access the business has. - /// - /// Patameters: String business_id. - /// - /// Returns List (List of access that match the above parameters). - static Future> getBusinessAccessListOfPatient( - String app_id) async { - final response = await http.get(Uri.parse( - "${AppEnviroment.baseApiUrl}/access-requests/personal/patient/$app_id")); - // var errorCode = response.statusCode.toString(); - // print(response.statusCode); - // print(response.body); - - if (response.statusCode == 200) { - Iterable l = jsonDecode(response.body); - List patientAccesses = List.from( - l.map((model) => PatientAccess.fromJson(model))); - return patientAccesses; - } else { - throw Exception('failed to pull patient access List for business'); - } - } - /// This function is used to UPDATE access the business has. /// /// Patameters:- @@ -336,12 +274,10 @@ class MIHApiCalls { /// Patameters: String dsearch. /// /// Returns List. + static Future> fetchPatients(String search) async { final response = await http .get(Uri.parse("${AppEnviroment.baseApiUrl}/patients/search/$search")); - // errorCode = response.statusCode.toString(); - // errorBody = response.body; - if (response.statusCode == 200) { Iterable l = jsonDecode(response.body); List patients = diff --git a/Frontend/lib/mih_services/mih_user_consent_services.dart b/Frontend/lib/mih_services/mih_user_consent_services.dart index f4246916..f55424f6 100644 --- a/Frontend/lib/mih_services/mih_user_consent_services.dart +++ b/Frontend/lib/mih_services/mih_user_consent_services.dart @@ -1,31 +1,39 @@ import 'dart:convert'; +import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/user_consent.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:provider/provider.dart'; import 'package:supertokens_flutter/http.dart' as http; import 'package:supertokens_flutter/supertokens.dart'; class MihUserConsentServices { - Future getUserConsentStatus() async { + Future getUserConsentStatus( + BuildContext context, + ) async { var app_id = await SuperTokens.getUserId(); final response = await http.get( Uri.parse("${AppEnviroment.baseApiUrl}/user-consent/user/$app_id")); if (response.statusCode == 200) { Map userMap = jsonDecode(response.body); UserConsent userConsent = UserConsent.fromJson(userMap); - return userConsent; - } else { - return null; + context.read().setUserConsent(userConsent); + // return userConsent; } + // else { + // return null; + // } } Future insertUserConsentStatus( - String app_id, String latestPrivacyPolicyDate, String latestTermOfServiceDate, + MzansiProfileProvider provider, + BuildContext context, ) async { UserConsent userConsent = UserConsent( - app_id: app_id, + app_id: provider.user!.app_id, privacy_policy_accepted: DateTime.parse(latestPrivacyPolicyDate), terms_of_services_accepted: DateTime.parse(latestTermOfServiceDate), ); @@ -34,16 +42,18 @@ class MihUserConsentServices { headers: {"Content-Type": "application/json"}, body: jsonEncode(userConsent.toJson()), ); + provider.setUserConsent(userConsent); return response.statusCode; } Future updateUserConsentStatus( - String app_id, String latestPrivacyPolicyDate, String latestTermOfServiceDate, + MzansiProfileProvider provider, + BuildContext context, ) async { UserConsent userConsent = UserConsent( - app_id: app_id, + app_id: provider.user!.app_id, privacy_policy_accepted: DateTime.parse(latestPrivacyPolicyDate), terms_of_services_accepted: DateTime.parse(latestTermOfServiceDate), ); @@ -52,6 +62,7 @@ class MihUserConsentServices { headers: {"Content-Type": "application/json"}, body: jsonEncode(userConsent.toJson()), ); + provider.setUserConsent(userConsent); return response.statusCode; } } diff --git a/Frontend/lib/mih_services/mih_user_services.dart b/Frontend/lib/mih_services/mih_user_services.dart index 44f83c87..0d8dadbb 100644 --- a/Frontend/lib/mih_services/mih_user_services.dart +++ b/Frontend/lib/mih_services/mih_user_services.dart @@ -1,15 +1,19 @@ import 'dart:convert'; import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; 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_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:provider/provider.dart'; import 'package:supertokens_flutter/http.dart' as http; import 'package:supertokens_flutter/supertokens.dart'; @@ -74,6 +78,7 @@ class MihUserServices { } Future> searchUsers( + MzansiProfileProvider profileProvider, String searchText, BuildContext context, ) async { @@ -87,6 +92,7 @@ class MihUserServices { Iterable l = jsonDecode(response.body); List users = List.from(l.map((model) => AppUser.fromJson(model))); + profileProvider.setUserearchResults(userSearchResults: users); return users; } else { throw Exception('failed to load users'); @@ -94,9 +100,9 @@ class MihUserServices { } Future getUserDetails( - String app_id, BuildContext context, ) async { + String app_id = await SuperTokens.getUserId(); var response = await http.get( Uri.parse("${AppEnviroment.baseApiUrl}/user/$app_id"), headers: { @@ -107,6 +113,9 @@ class MihUserServices { if (response.statusCode == 200) { String body = response.body; var jsonBody = jsonDecode(body); + context.read().setUser( + newUser: AppUser.fromJson(jsonBody), + ); return AppUser.fromJson(jsonBody); } else { return null; @@ -126,11 +135,13 @@ class MihUserServices { var fileName = profilePicture.replaceAll(RegExp(r' '), '-'); var filePath = "${signedInUser.app_id}/profile_files/$fileName"; String profileType; + KenLogger.success("is Busines User: $isBusinessUser"); if (isBusinessUser) { profileType = "business"; } else { profileType = "personal"; } + KenLogger.success("Profile Type: $profileType"); var response = await http.put( Uri.parse("${AppEnviroment.baseApiUrl}/user/update/v2/"), headers: { @@ -147,6 +158,21 @@ class MihUserServices { }), ); if (response.statusCode == 200) { + context.read().setUser( + newUser: AppUser( + signedInUser.idUser, + signedInUser.email, + firstName, + lastName, + profileType, + signedInUser.app_id, + username, + filePath, + purpose, + ), + ); + String newProPicUrl = await MihFileApi.getMinioFileUrl(filePath, context); + context.read().setUserProfilePicUrl(newProPicUrl); return response.statusCode; } else { return response.statusCode; @@ -192,7 +218,7 @@ class MihUserServices { } static Future deleteAccount( - String app_id, + MzansiProfileProvider provider, BuildContext context, ) async { loadingPopUp(context); @@ -202,7 +228,7 @@ class MihUserServices { "Content-Type": "application/json; charset=UTF-8" }, body: jsonEncode({ - "app_id": app_id, + "app_id": provider.user!.app_id, "env": AppEnviroment.getEnv(), }), ); @@ -212,18 +238,12 @@ class MihUserServices { print(error); }); if (await SuperTokens.doesSessionExist() == false) { - // Navigator.of(context).pop(); // Pop loading dialog - // Navigator.of(context).pop(); // Pop delete account dialog - // Navigator.of(context).pop(); // Pop Mzansi Profile - // Navigator.of(context).popAndPushNamed( - // '/', - // arguments: AuthArguments(true, false), - // ); //Pop and push to login page successPopUp( "Account Deleted Successfully", "Your account has been successfully deleted. We are sorry to see you go, but we respect your decision.", context, ); // Show success message. + provider.dispose(); } } else { Navigator.of(context).pop(); // Pop loading dialog diff --git a/Frontend/lib/mih_services/mih_validation_services.dart b/Frontend/lib/mih_services/mih_validation_services.dart index d7085268..8d750099 100644 --- a/Frontend/lib/mih_services/mih_validation_services.dart +++ b/Frontend/lib/mih_services/mih_validation_services.dart @@ -6,6 +6,17 @@ class MihValidationServices { return null; } + String? validateNoSpecialChars(String? value) { + if (value == null || value.isEmpty) { + return "This field is required"; + } + final specialCharRegex = RegExp(r"^[\w,'& ]+$"); + if (!specialCharRegex.hasMatch(value)) { + return "Only , ' & _ Special characters are allowed"; + } + return null; + } + String? validateLength(String? value, int maxLength) { if (value == null || value.isEmpty) { return "This field is required"; diff --git a/Frontend/pubspec.lock b/Frontend/pubspec.lock index 59bae95d..697e5b35 100644 --- a/Frontend/pubspec.lock +++ b/Frontend/pubspec.lock @@ -297,6 +297,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.2" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" custom_rating_bar: dependency: "direct main" description: @@ -1129,7 +1137,7 @@ packages: source: hosted version: "4.1.0" provider: - dependency: transitive + dependency: "direct main" description: name: provider sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" diff --git a/Frontend/pubspec.yaml b/Frontend/pubspec.yaml index bf372693..9969b895 100644 --- a/Frontend/pubspec.yaml +++ b/Frontend/pubspec.yaml @@ -1,7 +1,7 @@ name: mzansi_innovation_hub description: "" publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 1.2.1+99 +version: 1.2.2+99 # version: 1.1.1+97 #--- Updated version for upgrader package testing environment: @@ -13,6 +13,7 @@ dependencies: flutter_web_plugins: sdk: flutter + cupertino_icons: ^1.0.8 font_awesome_flutter: ^10.7.0 syncfusion_flutter_core: ^29.2.10 syncfusion_flutter_pdfviewer: ^29.2.10 @@ -57,6 +58,7 @@ dependencies: upgrader: ^12.0.0 screenshot: ^3.0.0 file_saver: ^0.3.1 + provider: ^6.1.5+1 dev_dependencies: flutter_test: diff --git a/backend/.DS_Store b/backend/.DS_Store index 74465b9f..051f6a8c 100644 Binary files a/backend/.DS_Store and b/backend/.DS_Store differ diff --git a/backend/main.py b/backend/main.py index 8210a6ad..37876e23 100644 --- a/backend/main.py +++ b/backend/main.py @@ -20,6 +20,7 @@ import routers.mzansi_wallet as mzansi_wallet import routers.mzansi_directory as mzansi_directory import routers.user_consent as user_consent import routers.icd10_codes as icd10_codes +import routers.mine_sweeper_leaderboard as mine_sweeper_leaderboard from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware import Middleware from supertokens_python import get_all_cors_headers @@ -98,6 +99,7 @@ app.include_router(mzansi_directory.router) app.include_router(user_consent.router) app.include_router(icd10_codes.router) app.include_router(appointments.router) +app.include_router(mine_sweeper_leaderboard.router) # Check if server is up @app.get("/", tags=["Server Check"]) diff --git a/backend/mih_database/mihDbObjects.py b/backend/mih_database/mihDbObjects.py index a1332903..dc888bb0 100644 --- a/backend/mih_database/mihDbObjects.py +++ b/backend/mih_database/mihDbObjects.py @@ -1,4 +1,4 @@ -from sqlalchemy import DateTime, Column, Integer, String, text +from sqlalchemy import DateTime, Column, Integer, String, DECIMAL, text from sqlalchemy.orm import declarative_base Base = declarative_base() @@ -83,6 +83,7 @@ class BookmarkedBusiness(Base): f"business_id='{self.business_id}', created_date='{self.created_date}')>" ) + class UserConsent(Base): __tablename__ = 'user_consent' __table_args__ = {'schema': 'app_data'} @@ -97,4 +98,24 @@ class UserConsent(Base): f"app_id='{self.app_id}', " f"privacy_policy_accepted='{self.privacy_policy_accepted}', " f"terms_of_services_accepted='{self.terms_of_services_accepted}')>" + ) + +class MineSweeperLeaderboard(Base): + __tablename__ = 'player_score' + __table_args__ = {'schema': 'minesweeper_leaderboard'} + idplayer_score = Column(Integer, primary_key=True) + app_id = Column(String(128), nullable=False,server_default=text("''")) + difficulty = Column(String(45), nullable=False,server_default=text("''")) + game_time = Column(String(45), nullable=False,server_default=text("''")) + game_score = Column(DECIMAL(45), nullable=False) + played_date = Column(DateTime, nullable=True) + + def __repr__(self): + return ( + f"" ) \ No newline at end of file diff --git a/backend/routers/mine_sweeper_leaderboard.py b/backend/routers/mine_sweeper_leaderboard.py new file mode 100644 index 00000000..1a665abe --- /dev/null +++ b/backend/routers/mine_sweeper_leaderboard.py @@ -0,0 +1,171 @@ +from fastapi import APIRouter, HTTPException, status +from pydantic import BaseModel +from supertokens_python.recipe.session.framework.fastapi import verify_session +from supertokens_python.recipe.session import SessionContainer +from fastapi import Depends +import mih_database +import mih_database.mihDbConnections +from mih_database.mihDbObjects import MineSweeperLeaderboard, User +from sqlalchemy import and_, func, literal_column +from sqlalchemy.orm import Session, aliased +from sqlalchemy.exc import IntegrityError, SQLAlchemyError +from datetime import datetime +from sqlalchemy.sql.expression import select + +router = APIRouter() + +class playerScoreInsertRequest(BaseModel): + app_id: str + difficulty: str + game_time: str + game_score: float + played_date: datetime + +# get top 20 scores +@router.get("/minesweeper/leaderboard/top20/{difficulty}", tags=["Minesweeper"]) +async def get_user_consent(difficulty: str, session: SessionContainer = Depends(verify_session())):#session: SessionContainer = Depends(verify_session()) + dbEngine = mih_database.mihDbConnections.dbAllConnect() + dbSession = Session(dbEngine) + try: + max_score_subquery = ( + dbSession.query( + MineSweeperLeaderboard.app_id, + func.max(MineSweeperLeaderboard.game_score).label('max_score') + ) + .filter(MineSweeperLeaderboard.difficulty == difficulty) + .group_by(MineSweeperLeaderboard.app_id) + .subquery('max_scores') + ) + queryResults = ( + dbSession.query(MineSweeperLeaderboard, User) + .join(User, User.app_id == MineSweeperLeaderboard.app_id) + .join( + max_score_subquery, + and_( + MineSweeperLeaderboard.app_id == max_score_subquery.c.app_id, + MineSweeperLeaderboard.game_score == max_score_subquery.c.max_score + ) + ) + .filter(MineSweeperLeaderboard.difficulty == difficulty) + .order_by(MineSweeperLeaderboard.game_score.desc()) + .limit(20) + .all() + ) + leaderboardData = [] + if queryResults: + for playerScore, user in queryResults: + leaderboardData.append({ + "app_id": playerScore.app_id, + "username": user.username, + "proPicUrl":user.pro_pic_path, + "difficulty":playerScore.difficulty, + "game_time":playerScore.game_time, + "game_score":playerScore.game_score, + "played_date":playerScore.played_date, + }) + return leaderboardData + else: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="No Score available for user." + ) + except HTTPException as http_exc: + raise http_exc + except Exception as e: + print(f"An error occurred during the ORM query: {e}") + if dbSession.is_active: + dbSession.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Failed to retrieve records due to an internal server error." + ) + finally: + dbSession.close() + +@router.get("/minesweeper/leaderboard/top_score/{difficulty}/{app_id}", tags=["Minesweeper"]) +async def get_user_consent(app_id: str, + difficulty: str, + session: SessionContainer = Depends(verify_session())):#session: SessionContainer = Depends(verify_session()) + dbEngine = mih_database.mihDbConnections.dbAllConnect() + dbSession = Session(dbEngine) + try: + queryResults =(dbSession.query(MineSweeperLeaderboard, User) + .join(User, User.app_id == MineSweeperLeaderboard.app_id) + .filter( + and_( + MineSweeperLeaderboard.app_id == app_id, + MineSweeperLeaderboard.difficulty == difficulty + ) + ) + .order_by(MineSweeperLeaderboard.game_score.desc()) + .all()) + if not queryResults: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="No scores found for this user and difficulty level." + ) + leaderboard_data = [] + for player_score, user in queryResults: + score_data = { + "app_id": player_score.app_id, + "username": user.username, + "proPicUrl": user.pro_pic_path, + "difficulty": player_score.difficulty, + "game_time": player_score.game_time, + "game_score": player_score.game_score, + "played_date": player_score.played_date, + } + leaderboard_data.append(score_data) + return leaderboard_data + except HTTPException as http_exc: + raise http_exc + except Exception as e: + print(f"An error occurred during the ORM query: {e}") + if dbSession.is_active: + dbSession.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Failed to retrieve records due to an internal server error." + ) + finally: + dbSession.close() + +@router.post("/minesweeper/leaderboard/player_score/insert/", + tags=["Minesweeper"], + status_code=status.HTTP_201_CREATED) +async def insert_user_consent(itemRequest: playerScoreInsertRequest, + session: SessionContainer = Depends(verify_session())):#session: SessionContainer = Depends(verify_session()) + dbEngine = mih_database.mihDbConnections.dbAllConnect() + dbSession = Session(dbEngine) + try: + newPlayerScore = MineSweeperLeaderboard( + app_id = itemRequest.app_id, + difficulty = itemRequest.difficulty, + game_time = itemRequest.game_time, + game_score = itemRequest.game_score, + played_date = itemRequest.played_date, + ) + dbSession.add(newPlayerScore) + dbSession.commit() + dbSession.refresh(newPlayerScore) + return {"message": "Successfully Created Player Score Record"} + except IntegrityError as e: + dbSession.rollback() + raise HTTPException( + status_code=status.HTTP_409_CONFLICT, # 409 Conflict is often suitable for constraint errors + detail=f"Data integrity error: The provided data violates a database constraint. Details: {e.orig}" + ) from e + except SQLAlchemyError as e: + dbSession.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"A database error occurred during insertion. Details: {e.orig}" + ) from e + except Exception as e: + dbSession.rollback() + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"An unexpected error occurred: {e}" + ) from e + finally: + dbSession.close() diff --git a/backend/routers/users.py b/backend/routers/users.py index 5aede146..a065e41b 100644 --- a/backend/routers/users.py +++ b/backend/routers/users.py @@ -249,6 +249,7 @@ async def delete_users_data_by_app_id(itemRequest: userDeleteRequest, session: "DELETE FROM patient_manager.patient_notes where app_id = %s", "DELETE FROM patient_manager.patient_files where app_id = %s", "DELETE FROM patient_manager.claim_statement_file where app_id = %s", + "DELETE FROM app_data.user_consent where app_id = %s", "DELETE FROM app_data.users where app_id = %s", ] # Delete user from all tables