diff --git a/.DS_Store b/.DS_Store index b2d3ca66..d4d2f162 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/Frontend/ios/Runner/Info.plist b/Frontend/ios/Runner/Info.plist index 53e112f3..2a54c123 100644 --- a/Frontend/ios/Runner/Info.plist +++ b/Frontend/ios/Runner/Info.plist @@ -2,6 +2,8 @@ + ITSAppUsesNonExemptEncryption + SKAdNetworkItems 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 8c52c32c..61abe627 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 @@ -12,10 +12,28 @@ class MihBannerAd extends StatefulWidget { } class _MihBannerAdState extends State { + @override + void dispose() { + super.dispose(); + } + + @override + void initState() { + super.initState(); + MihBannerAdProvider adProvider = context.read(); + WidgetsBinding.instance.addPostFrameCallback((_) { + adProvider.reset(); + adProvider.loadBannerAd(); + }); + } + @override Widget build(BuildContext context) { return Consumer( builder: (context, bannerAdProvider, child) { + if (!bannerAdProvider.isBannerAdLoaded) { + return SizedBox(); + } return Column( children: [ bannerAdProvider.bannerAd != null && 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 53683653..e8968df5 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 @@ -41,8 +41,6 @@ class _MihBusinessProfilePreviewState extends State { @override void initState() { super.initState(); - futureImageUrl = - MihFileApi.getMinioFileUrl(widget.business.logo_path, context); } @override @@ -54,7 +52,8 @@ class _MihBusinessProfilePreviewState extends State { return Row( children: [ FutureBuilder( - future: futureImageUrl, + future: MihFileApi.getMinioFileUrl( + widget.business.logo_path, context), builder: (context, asyncSnapshot) { if (asyncSnapshot.connectionState == ConnectionState.done && asyncSnapshot.hasData) { 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 index 560fc91a..394bcbb4 100644 --- a/Frontend/lib/mih_components/mih_providers/mih_banner_ad_provider.dart +++ b/Frontend/lib/mih_components/mih_providers/mih_banner_ad_provider.dart @@ -28,6 +28,11 @@ class MihBannerAdProvider extends ChangeNotifier { } void loadBannerAd() { + if (bannerAd != null) { + bannerAd!.dispose(); + bannerAd = null; + isBannerAdLoaded = false; + } bannerAd = BannerAd( adUnitId: adUnitId, request: const AdRequest(), diff --git a/Frontend/lib/mih_components/mih_providers/mih_calendar_provider.dart b/Frontend/lib/mih_components/mih_providers/mih_calendar_provider.dart index 40265f45..fe4ee6b6 100644 --- a/Frontend/lib/mih_components/mih_providers/mih_calendar_provider.dart +++ b/Frontend/lib/mih_components/mih_providers/mih_calendar_provider.dart @@ -1,4 +1,5 @@ import 'package:flutter/foundation.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/appointment.dart'; class MihCalendarProvider extends ChangeNotifier { @@ -57,6 +58,7 @@ class MihCalendarProvider extends ChangeNotifier { int index = personalAppointments?.indexWhere((appointment) => appointment.idappointments == updatedAppointment.idappointments) ?? -1; + KenLogger.success("Edit Patient Index: $index"); if (index != -1) { personalAppointments?[index] = updatedAppointment; 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 index 59f148bc..ef05f620 100644 --- a/Frontend/lib/mih_components/mih_providers/mzansi_directory_provider.dart +++ b/Frontend/lib/mih_components/mih_providers/mzansi_directory_provider.dart @@ -10,7 +10,7 @@ class MzansiDirectoryProvider extends ChangeNotifier { String userLocation; bool personalSearch; List bookmarkedBusinesses = []; - Map businessDetailsMap = {}; + List? favouriteBusinessesList; List? searchedBusinesses; Business? selectedBusiness; List? searchedUsers; @@ -32,7 +32,6 @@ class MzansiDirectoryProvider extends ChangeNotifier { userLocation = "Unknown Location"; personalSearch = true; bookmarkedBusinesses = []; - businessDetailsMap = {}; searchedBusinesses = null; selectedBusiness = null; searchedUsers = null; @@ -62,13 +61,14 @@ class MzansiDirectoryProvider extends ChangeNotifier { notifyListeners(); } - void setFavouriteBusinesses({required List businesses}) { + void setBookmarkedeBusinesses( + {required List businesses}) { bookmarkedBusinesses = businesses; notifyListeners(); } - void setBusinessDetailsMap({required Map detailsMap}) { - businessDetailsMap = detailsMap; + void setFavouriteBusinesses({required List businesses}) { + favouriteBusinessesList = businesses; 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 index f09a3135..e7904531 100644 --- a/Frontend/lib/mih_components/mih_providers/mzansi_wallet_provider.dart +++ b/Frontend/lib/mih_components/mih_providers/mzansi_wallet_provider.dart @@ -33,11 +33,6 @@ class MzansiWalletProvider extends ChangeNotifier { notifyListeners(); } - void addLoyaltyCard({required MIHLoyaltyCard newCard}) { - loyaltyCards.add(newCard); - notifyListeners(); - } - void deleteLoyaltyCard({required int cardId}) { loyaltyCards.removeWhere((card) => card.idloyalty_cards == cardId); notifyListeners(); diff --git a/Frontend/lib/mih_config/mih_go_router.dart b/Frontend/lib/mih_config/mih_go_router.dart index 71de50cc..685ce86b 100644 --- a/Frontend/lib/mih_config/mih_go_router.dart +++ b/Frontend/lib/mih_config/mih_go_router.dart @@ -17,7 +17,7 @@ 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/busines_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/mzansi_set_up_business_profile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart'; @@ -190,9 +190,10 @@ class MihGoRouter { }); return const SizedBox.shrink(); } - return MzansiBusinessProfile( - key: UniqueKey(), - ); + return BusinesProfile(); + // return MzansiBusinessProfile( + // key: UniqueKey(), + // ); }, ), GoRoute( diff --git a/Frontend/lib/mih_packages/calculator/mih_calculator.dart b/Frontend/lib/mih_packages/calculator/mih_calculator.dart index e0ed5add..775a868e 100644 --- a/Frontend/lib/mih_packages/calculator/mih_calculator.dart +++ b/Frontend/lib/mih_packages/calculator/mih_calculator.dart @@ -2,7 +2,6 @@ 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'; @@ -29,7 +28,6 @@ class _MIHCalculatorState extends State { void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) async { - context.read().loadBannerAd(); await getCurrencyCodeList(); }); } 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 b0680632..6fabe709 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,7 +9,6 @@ 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_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'; @@ -67,7 +66,6 @@ class _CurrencyExchangeRateState extends State { fullscreen: false, windowTitle: "Calculation Results", onWindowTapClose: () { - context.read().loadBannerAd(); Navigator.pop(context); }, windowBody: Column( 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 229dbd1e..58583291 100644 --- a/Frontend/lib/mih_packages/calculator/package_tools/tip_calc.dart +++ b/Frontend/lib/mih_packages/calculator/package_tools/tip_calc.dart @@ -1,6 +1,5 @@ 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'; @@ -99,7 +98,6 @@ class _TipCalcState extends State { fullscreen: false, windowTitle: "Calculation Results", onWindowTapClose: () { - context.read().loadBannerAd(); Navigator.pop(context); }, windowBody: Column( 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 d56ef908..32481014 100644 --- a/Frontend/lib/mih_packages/calendar/builder/build_appointment_list.dart +++ b/Frontend/lib/mih_packages/calendar/builder/build_appointment_list.dart @@ -3,7 +3,6 @@ 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'; @@ -59,6 +58,13 @@ class _BuildAppointmentListState extends State { late double width; late double height; + void clearControllers() { + widget.titleController.clear(); + widget.descriptionIDController.clear(); + widget.dateController.clear(); + widget.timeController.clear(); + } + double getPaddingSize() { if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") { return (width / 10); @@ -72,37 +78,41 @@ class _BuildAppointmentListState extends State { 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)); + + // SAFELY EXTRACT DATE AND TIME + String dateTimeString = appointmentList[index].date_time; + String timePart = ""; + String datePart = ""; + + if (dateTimeString.contains("T")) { + List parts = dateTimeString.split('T'); + datePart = parts[0]; + timePart = parts[1].substring(0, 5); + } else if (dateTimeString.contains(" ")) { + List parts = dateTimeString.split(' '); + datePart = parts[0]; + timePart = parts[1].substring(0, 5); } 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)); + // Fallback if format is unexpected + datePart = dateTimeString; + timePart = "00:00"; } + + String heading = + "$timePart - ${appointmentList[index].title.toUpperCase()}"; + String description = appointmentList[index].description; + + DateTime now = DateTime.now(); + int hourNow = int.parse(now.toString().split(' ')[1].substring(0, 2)); + String currentDate = + DateTime(now.year, now.month, now.day).toString().split(' ')[0]; + + int appointHour = int.parse(timePart.split(':')[0]); + Color appointmentColor = MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"); - if (date == appointDate) { + + if (currentDate == datePart) { if (appointHour < hourNow) { appointmentColor = MihColors.getGreyColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"); @@ -110,7 +120,7 @@ class _BuildAppointmentListState extends State { appointmentColor = MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"); } - } else if (DateTime.parse(appointDate).isBefore(DateTime.parse(date))) { + } else if (DateTime.parse(datePart).isBefore(DateTime.parse(currentDate))) { appointmentColor = MihColors.getGreyColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"); } @@ -138,15 +148,15 @@ class _BuildAppointmentListState extends State { ), ), onTap: () { + // SAFELY SET CONTROLLER VALUES setState(() { widget.titleController.text = appointmentList[index].title; widget.descriptionIDController.text = appointmentList[index].description; - widget.dateController.text = - appointmentList[index].date_time.split('T')[0]; - widget.timeController.text = - appointmentList[index].date_time.split('T')[1].substring(0, 5); + widget.dateController.text = datePart; + widget.timeController.text = timePart; }); + if (widget.inWaitingRoom == false) { appointmentDetailsWindow( mzansiProfileProvider, mihCalendarProvider, index, bodyWidth); @@ -214,10 +224,7 @@ class _BuildAppointmentListState extends State { ], onWindowTapClose: () { context.pop(); - widget.dateController.clear(); - widget.timeController.clear(); - widget.titleController.clear(); - widget.descriptionIDController.clear(); + clearControllers(); }, windowBody: Padding( padding: @@ -342,10 +349,7 @@ class _BuildAppointmentListState extends State { ], onWindowTapClose: () { context.pop(); - widget.dateController.clear(); - widget.timeController.clear(); - widget.titleController.clear(); - widget.descriptionIDController.clear(); + clearControllers(); }, windowBody: Padding( padding: @@ -591,6 +595,7 @@ class _BuildAppointmentListState extends State { List appointmentList = mzansiProfileProvider.personalHome ? mihCalendarProvider.personalAppointments! : mihCalendarProvider.businessAppointments!; + KenLogger.success("ersonalHome: ${mzansiProfileProvider.personalHome}"); if (mzansiProfileProvider.personalHome == true) { statusCode = await MihMzansiCalendarApis.updatePersonalAppointment( mzansiProfileProvider.user!, @@ -634,28 +639,30 @@ class _BuildAppointmentListState extends State { if (statusCode == 200) { context.pop(); context.pop(); - if (!widget.inWaitingRoom) { - KenLogger.warning("calendar route"); - context.goNamed( - "mihCalendar", - ); - } else { - KenLogger.warning("waiting room route"); - // GoRouter.of(context).refresh(); - context.goNamed( - 'mihHome', - ); - context.goNamed( - 'patientManager', - extra: PatManagerArguments( - mzansiProfileProvider.user!, - false, - mzansiProfileProvider.business, - mzansiProfileProvider.businessUser, - ), - ); - // context.pop(); - } + successPopUp("Successfully Updated Appointment", + "You appointment has been successfully updated."); + // if (!widget.inWaitingRoom) { + // KenLogger.warning("calendar route"); + // context.goNamed( + // "mihCalendar", + // ); + // } else { + // KenLogger.warning("waiting room route"); + // // GoRouter.of(context).refresh(); + // context.goNamed( + // 'mihHome', + // ); + // context.goNamed( + // 'patientManager', + // extra: PatManagerArguments( + // mzansiProfileProvider.user!, + // false, + // mzansiProfileProvider.business, + // mzansiProfileProvider.businessUser, + // ), + // ); + // // context.pop(); + // } } else { internetConnectionPopUp(); } @@ -724,6 +731,7 @@ class _BuildAppointmentListState extends State { child: MihButton( onPressed: () { context.pop(); + clearControllers(); }, buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -805,15 +813,17 @@ class _BuildAppointmentListState extends State { MzansiProfileProvider mzansiProfileProvider, MihCalendarProvider mihCalendarProvider, Widget? child) { - List appointmentList = mzansiProfileProvider.personalHome - ? mihCalendarProvider.personalAppointments! - : mihCalendarProvider.businessAppointments!; + // 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, + itemCount: mzansiProfileProvider.personalHome + ? mihCalendarProvider.personalAppointments!.length + : mihCalendarProvider.businessAppointments!.length, itemBuilder: (context, index) { return displayAppointment( mzansiProfileProvider, mihCalendarProvider, index, width); diff --git a/Frontend/lib/mih_packages/calendar/package_tools/appointments.dart b/Frontend/lib/mih_packages/calendar/package_tools/appointments.dart index 1d198a82..26e3b59a 100644 --- a/Frontend/lib/mih_packages/calendar/package_tools/appointments.dart +++ b/Frontend/lib/mih_packages/calendar/package_tools/appointments.dart @@ -139,7 +139,7 @@ class _PatientAccessRequestState extends State { fullscreen: false, windowTitle: "Add Appointment", onWindowTapClose: () { - Navigator.of(context).pop(); + context.pop(); _appointmentDateController.clear(); _appointmentTimeController.clear(); _appointmentTitleController.clear(); 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 index 3facf977..c701be22 100644 --- 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 @@ -13,7 +13,6 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ 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'; @@ -124,8 +123,9 @@ class _MineSweeperGameState extends State { return '$hoursStr:$minutesStr:$secondsStr:$centiStr'; } - void showStartGameWindow(MihMineSweeperProvider mihMineSweeperProvider, - MihBannerAdProvider addProvider) { + void showStartGameWindow( + MihMineSweeperProvider mihMineSweeperProvider, + ) { // easy - 10 * 10 & 15 bombs // Intermediate - 10 * 15 & 23 bombs // Hard - 10 * 20 & 30 bombs @@ -134,7 +134,6 @@ class _MineSweeperGameState extends State { builder: (context) { return MihMineSweeperStartGameWindow( onPressed: () { - addProvider.loadBannerAd(); resetTimer(); mihMineSweeperProvider .setDifficulty(mihMineSweeperProvider.difficulty); @@ -241,12 +240,8 @@ class _MineSweeperGameState extends State { } } - Future handleTap( - MzansiProfileProvider profileProvider, - MihMineSweeperProvider mihMineSweeperProvider, - MihBannerAdProvider adProvider, - int r, - int c) async { + Future handleTap(MzansiProfileProvider profileProvider, + MihMineSweeperProvider mihMineSweeperProvider, int r, int c) async { if (isGameOver || board[r][c].isOpened || board[r][c].isFlagged) { return; } @@ -304,8 +299,7 @@ class _MineSweeperGameState extends State { MihButton( onPressed: () { context.pop(); - showStartGameWindow( - mihMineSweeperProvider, adProvider); + showStartGameWindow(mihMineSweeperProvider); }, buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == @@ -364,7 +358,7 @@ class _MineSweeperGameState extends State { squaresLeft--; } // 3. Check for win - _checkWinCondition(profileProvider, mihMineSweeperProvider, adProvider); + _checkWinCondition(profileProvider, mihMineSweeperProvider); // Update the UI setState(() {}); } @@ -383,7 +377,6 @@ class _MineSweeperGameState extends State { Future _checkWinCondition( MzansiProfileProvider profileProvider, MihMineSweeperProvider mihMineSweeperProvider, - MihBannerAdProvider adProvider, ) async { // Game is won if all non-mine squares are opened. if (squaresLeft <= mihMineSweeperProvider.totalMines) { @@ -450,7 +443,7 @@ class _MineSweeperGameState extends State { MihButton( onPressed: () { context.pop(); - showStartGameWindow(mihMineSweeperProvider, adProvider); + showStartGameWindow(mihMineSweeperProvider); }, buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == @@ -558,13 +551,9 @@ class _MineSweeperGameState extends State { } Widget getBody() { - return Consumer3( - builder: (BuildContext context, - MzansiProfileProvider profileProvider, - MihMineSweeperProvider mihMineSweeperProvider, - MihBannerAdProvider adProvider, - Widget? child) { + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + MihMineSweeperProvider mihMineSweeperProvider, Widget? child) { return Column( children: [ Expanded( @@ -725,12 +714,8 @@ class _MineSweeperGameState extends State { return MineTile( square: board[r][c], - onTap: () => handleTap( - profileProvider, - mihMineSweeperProvider, - adProvider, - r, - c), + onTap: () => handleTap(profileProvider, + mihMineSweeperProvider, r, c), onLongPress: () => handleLongPress(r, c), ); }, @@ -768,7 +753,7 @@ class _MineSweeperGameState extends State { MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - mihMineSweeperProvider.setToolIndex(2); + mihMineSweeperProvider.setToolIndex(3); }, ), SpeedDialChild( @@ -778,9 +763,7 @@ class _MineSweeperGameState extends State { MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), - label: board.isEmpty && squaresLeft < 0 - ? "Start Game" - : "Reset Game", + label: "Start New Game", labelBackgroundColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -794,8 +777,7 @@ class _MineSweeperGameState extends State { MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onTap: () { - showStartGameWindow( - mihMineSweeperProvider, adProvider); + showStartGameWindow(mihMineSweeperProvider); }, ), ]), 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 index 2bd762c7..6e4144c0 100644 --- 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 @@ -14,163 +14,821 @@ class MineSweeperQuickStartGuide extends StatefulWidget { 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"), - ), - ); - } + double titleSize = 22.0; + double subtitleSize = 20.0; + double pointsSize = 18.0; - Widget _buildSubSectionTitle(String title) { - return Text( - title, - style: TextStyle( - fontSize: 17, - fontWeight: FontWeight.w600, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + Widget sectionOne() { + return Container( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode != "Darl"), + borderRadius: BorderRadius.circular(15), ), - ); - } - - 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, + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + // Title + Text( + "1. Two Main Actions\n(Your Controls)", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: titleSize, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), ), - ), - ...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( + const SizedBox(height: 8), + //Part One + 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), + text: 'Quick Tap (or Click): This is the Dig action.', + style: TextStyle( + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: subtitleSize, + ), + ), ], ), ), - ), - ], - ), - ); - } - - 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"), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: '• Goal:', + style: TextStyle( + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: ' To uncover a square and see a number clue.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], ), ), - TextSpan(text: isAction ? ' $explanation' : ': $explanation'), - ], + ), ), - ), - ], + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.centerLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: '• Risk:', + style: TextStyle( + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: ' If you click a mine, the game ends!', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + const SizedBox(height: 8), + //Part Two + RichText( + text: TextSpan( + children: [ + TextSpan( + text: + 'Tap and Hold (or Long Press): This is the Flag action (🚩).', + style: TextStyle( + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: subtitleSize, + ), + ), + ], + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: '• Goal:', + style: TextStyle( + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: ' To safely mark a square that you are', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + TextSpan( + text: ' certain', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: ' is a mine.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.centerLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: '• Risk:', + style: TextStyle( + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: + ' Accidental placement of flags will cause confusion.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.centerLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: '• Benefit:', + style: TextStyle( + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: + ' You cannot accidentally click a square that is flagged.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + ], + ), ), ); } - 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('• ', + Widget sectionTwo() { + return Container( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode != "Darl"), + borderRadius: BorderRadius.circular(15), + ), + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + // Title + Text( + "2. The Golden Rule\n(Reading the Numbers)", + textAlign: TextAlign.center, style: TextStyle( - fontSize: 18, - color: MihColors.getBronze( - MzansiInnovationHub.of(context)!.theme.mode != "Dark"), - fontWeight: FontWeight.bold)), - Expanded( - child: RichText( + fontSize: titleSize, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + const SizedBox(height: 8), + //Part One + 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), + text: + 'The number tells you exactly how many mines are touching that square (including sides and corners).', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: subtitleSize, + ), + ), ], ), ), - ), - ], + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: "• If you see a Blank Space (a '0'):", + style: TextStyle( + color: MihColors.getOrangeColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: " Zero (0) ", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: + ' mines are touching it. All surrounding squares are safe, and the game will open them for you automatically.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.centerLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: "• If you see a '1':", + style: TextStyle( + color: MihColors.getOrangeColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: ' Only ', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + TextSpan( + text: 'one', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: + ' mine is touching this square. You must find and flag that single mine.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: "• If you see a '3':", + style: TextStyle( + color: MihColors.getOrangeColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: " Three ", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: + 'mines are touching this square. You must find and flag all three.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ); + } + + Widget sectionThree() { + return Container( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode != "Darl"), + borderRadius: BorderRadius.circular(15), + ), + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + // Title + Text( + "3. The Winning Strategy\n(The Deduction Loop)", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: titleSize, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + const SizedBox(height: 8), + //Part One + RichText( + text: TextSpan( + children: [ + TextSpan( + 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( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: subtitleSize, + ), + ), + ], + ), + ), + const SizedBox(height: 8), + RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'A. Find the Mines (Where to Flag 🚩)', + style: TextStyle( + color: MihColors.getPurpleColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: subtitleSize, + ), + ), + ], + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: '• Goal:', + style: TextStyle( + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: + ' Look for a number that only has one choice for a mine. e.g. If a \'1\' is touching only one hidden square, that hidden square', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + TextSpan( + text: ' must ', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: 'be the mine.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.centerLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: '• Action:', + style: TextStyle( + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: ' Tap and Hold to place a', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + TextSpan( + text: ' Flag ', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: 'on the square you are sure is a mine.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + const SizedBox(height: 8), + //Part Two + RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'B. Find the Safe Squares (Where to Dig)', + style: TextStyle( + color: MihColors.getPurpleColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: subtitleSize, + ), + ), + ], + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: '• Goal:', + style: TextStyle( + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: + ' Look for a number that has been \'satisfied\' by your flags. e.g. You see a \'2\' and you have already placed two 🚩 flags touching it. The \'2\' is satisfied.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.centerLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: '• Action:', + style: TextStyle( + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode != + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: + ' Quick Tap any of the remaining hidden squares touching that \'satisfied\' number. They', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + TextSpan( + text: ' must be safe ', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: + 'because the mine requirement has already been met.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + ], + ), + ), + ); + } + + Widget sectionFour() { + return Container( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode != "Darl"), + borderRadius: BorderRadius.circular(15), + ), + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + // Title + Text( + "✨ Key Beginner Tips", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: titleSize, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: "• Start on the Edges and Corners: ", + style: TextStyle( + color: MihColors.getBronze( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: + 'Numbers on the edge or corner of the board are easier to solve because they have fewer surrounding squares to check.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Align( + alignment: Alignment.topLeft, + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: "• Don't Guess: ", + style: TextStyle( + color: MihColors.getBronze( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + fontSize: pointsSize, + ), + ), + TextSpan( + text: + '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.', + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.normal, + fontSize: pointsSize, + ), + ), + ], + ), + ), + ), + ), + ], + ), ), ); } @@ -202,146 +860,18 @@ class _MineSweeperQuickStartGuideState 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), + style: TextStyle(fontSize: 18), ), // 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), - ], - ), - ), + sectionOne(), 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), - ], - ), - ), + sectionTwo(), 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), - ], - ), - ), + sectionThree(), + const SizedBox(height: 15), + sectionFour(), 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/mzansi_ai/package_tools/ai_chat.dart b/Frontend/lib/mih_packages/mzansi_ai/package_tools/ai_chat.dart index c380456f..8119d6a2 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 @@ -93,6 +93,8 @@ class _AiChatState extends State { temp += "- Calculator: Simple calculator with tip and forex calculation functionality.\n"; temp += "- MIH Access: Manage and view profile access security.\n"; + temp += + "- MIH Minesweeper: The first game from MIH! It's the classic brain-teaser ready to entertain you no matter where you are.\n"; temp += "**Core Rules and Guidelines:**\n"; temp += "- **Accuracy First:** Always prioritize providing correct information.\n"; 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 8f4e638d..94e2d5ae 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 @@ -47,7 +47,7 @@ class _BuildFavouriteBusinessesListState directoryProvider.setSelectedBusiness( business: widget.favouriteBusinesses[index]!, ); - context.goNamed( + context.pushNamed( 'businessProfileView', ); }, diff --git a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart index baa1dda3..5ddca512 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart @@ -1,13 +1,18 @@ import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.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: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_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_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart'; import 'package:provider/provider.dart'; class MzansiDirectory extends StatefulWidget { @@ -31,11 +36,33 @@ class _MzansiDirectoryState extends State { }); } + Future getFavouriteBusinesses() async { + MzansiDirectoryProvider directoryProvider = + context.read(); + MzansiProfileProvider profileProvider = + context.read(); + await MihMzansiDirectoryServices().getAllUserBookmarkedBusiness( + profileProvider.user!.app_id, + directoryProvider, + ); + List favBus = []; + for (var bus in directoryProvider.bookmarkedBusinesses) { + await MihBusinessDetailsServices() + .getBusinessDetailsByBusinessId(bus.business_id) + .then((business) { + favBus.add(business!); + }); + } + KenLogger.success(favBus); + directoryProvider.setFavouriteBusinesses(businesses: favBus); + } + @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) async { initialiseGPSLocation(); + getFavouriteBusinesses(); }); } 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 eeb53ba0..ffc1646b 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,17 +1,16 @@ import 'dart:async'; 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/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:provider/provider.dart'; class MihFavouriteBusinesses extends StatefulWidget { @@ -31,38 +30,13 @@ class _MihFavouriteBusinessesState extends State { ValueNotifier([]); Timer? _debounce; - Future getAndMapAllBusinessDetailsForBookmarkedBusinesses( - MzansiProfileProvider mzansiProfileProvider, - MzansiDirectoryProvider directoryProvider, - ) async { - await MihMzansiDirectoryServices().getAllUserBookmarkedBusiness( - mzansiProfileProvider.user!.app_id, - directoryProvider, - ); - Map businessMap = {}; - List> detailFutures = []; - for (var item in directoryProvider.bookmarkedBusinesses) { - detailFutures.add(MihBusinessDetailsServices() - .getBusinessDetailsByBusinessId(item.business_id)); - } - List details = await Future.wait(detailFutures); - for (int i = 0; i < directoryProvider.bookmarkedBusinesses.length; i++) { - businessMap[directoryProvider.bookmarkedBusinesses[i].business_id] = - details[i]; - } - directoryProvider.setBusinessDetailsMap(detailsMap: businessMap); - _filterAndSetBusinesses(directoryProvider); - } - void _filterAndSetBusinesses(MzansiDirectoryProvider directoryProvider) { List businessesToDisplay = []; String query = businessSearchController.text.toLowerCase(); - for (var bookmarked in directoryProvider.bookmarkedBusinesses) { - if (bookmarked.business_name.toLowerCase().contains(query)) { - if (directoryProvider.businessDetailsMap - .containsKey(bookmarked.business_id)) { - businessesToDisplay.add( - directoryProvider.businessDetailsMap[bookmarked.business_id]); + if (directoryProvider.favouriteBusinessesList != null) { + for (var bus in directoryProvider.favouriteBusinessesList!) { + if (bus.Name.toLowerCase().contains(query)) { + businessesToDisplay.add(bus); } } } @@ -82,13 +56,11 @@ class _MihFavouriteBusinessesState extends State { super.initState(); MzansiDirectoryProvider directoryProvider = context.read(); - MzansiProfileProvider mzansiProfileProvider = - context.read(); - - getAndMapAllBusinessDetailsForBookmarkedBusinesses( - mzansiProfileProvider, - directoryProvider, - ); + // getAndMapAllBusinessDetailsForBookmarkedBusinesses( + // mzansiProfileProvider, + // directoryProvider, + // ); + _filterAndSetBusinesses(directoryProvider); businessSearchController.addListener(() { if (_debounce?.isActive ?? false) { _debounce!.cancel(); @@ -110,116 +82,129 @@ class _MihFavouriteBusinessesState extends State { } Widget getBody(double width) { - return MihSingleChildScroll( - child: Column( - children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: width / 20), - child: MihSearchBar( - controller: businessSearchController, - hintText: "Search Businesses", - prefixIcon: Icons.search, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - hintColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onPrefixIconTap: () {}, - searchFocusNode: searchFocusNode, - ), - ), - const SizedBox(height: 10), - 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 (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, + return Consumer( + builder: (BuildContext context, MzansiDirectoryProvider directoryProvider, + Widget? child) { + if (directoryProvider.favouriteBusinessesList == null) { + return Center( + child: Mihloadingcircle(), + ); + } + return MihSingleChildScroll( + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: MihSearchBar( + controller: businessSearchController, + hintText: "Search Businesses", + prefixIcon: Icons.search, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + hintColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onPrefixIconTap: () {}, + searchFocusNode: searchFocusNode, + ), + ), + const SizedBox(height: 10), + 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: 25), - Center( - child: RichText( + const SizedBox(height: 10), + Text( + "Let's try refining your search", textAlign: TextAlign.center, - text: TextSpan( + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ], + ); + } 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: 20, - fontWeight: FontWeight.normal, + 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"), + TextSpan( + text: + " to find your favourite businesses of mzansi"), + ], + ), + ), + ), + ], ), - ], - ), - ); - } - return BuildFavouriteBusinessesList( - favouriteBusinesses: filteredBusinesses, - ); - }), - ], - ), + ); + } + KenLogger.success(filteredBusinesses); + return BuildFavouriteBusinessesList( + favouriteBusinesses: filteredBusinesses, + ); + }), + ], + ), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/busines_profile.dart similarity index 82% rename from Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart rename to Frontend/lib/mih_packages/mzansi_profile/business_profile/busines_profile.dart index 69dd98ea..fbf3cbb7 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/busines_profile.dart @@ -1,34 +1,45 @@ +import 'package:flutter/material.dart'; import 'package:go_router/go_router.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_providers/mzansi_profile_provider.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:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_user.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_employee_services.dart'; import 'package:provider/provider.dart'; -class MzansiBusinessProfile extends StatefulWidget { - const MzansiBusinessProfile({ - super.key, - }); +class BusinesProfile extends StatefulWidget { + const BusinesProfile({super.key}); @override - State createState() => _MzansiBusinessProfileState(); + State createState() => _BusinesProfileState(); } -class _MzansiBusinessProfileState extends State { +class _BusinesProfileState extends State { + Future initialiseBusinessData() async { + MzansiProfileProvider profileProvider = + context.read(); + await MihBusinessEmployeeServices() + .fetchEmployees(profileProvider, context); + } + + @override + void initState() { + super.initState(); + initialiseBusinessData(); + } + @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); @@ -45,7 +56,6 @@ class _MzansiBusinessProfileState extends State { 'mihHome', ); FocusScope.of(context).unfocus(); - context.read().setBusinessIndex(0); }, ); } @@ -79,22 +89,6 @@ class _MzansiBusinessProfileState extends State { ); } - List getToolBody() { - List toolBodies = [ - MihBusinessDetails(), - MihMyBusinessUser(), - MihMyBusinessTeam(), - MihBusinessUserSearch(), - MihBusinessReviews( - business: context.watch().business!), - MihBusinessQrCode( - business: context.watch().business!, - // startUpSearch: "", - ), - ]; - return toolBodies; - } - List getToolTitle() { List toolTitles = [ "Profile", @@ -106,4 +100,16 @@ class _MzansiBusinessProfileState extends State { ]; return toolTitles; } + + List getToolBody() { + List toolBodies = [ + MihBusinessDetails(), + MihMyBusinessUser(), + MihMyBusinessTeam(), + MihBusinessUserSearch(), + MihBusinessReviews(business: null), + MihBusinessQrCode(business: null), + ]; + return toolBodies; + } } 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 268c768f..109de674 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 @@ -14,22 +14,22 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ 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_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_config/mih_env.dart'; 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:provider/provider.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 Business? business; const MihBusinessQrCode({ super.key, required this.business, - // required this.startUpSearch, }); @override @@ -38,6 +38,7 @@ class MihBusinessQrCode extends StatefulWidget { class _MihBusinessQrCodeState extends State { late Future futureImageUrl; + late Business business; PlatformFile? file; late String qrCodedata; int qrSize = 500; @@ -66,14 +67,14 @@ class _MihBusinessQrCodeState extends State { .substring(2, 8); // KenLogger.warning(bgColor); String encodedData = - Uri.encodeComponent("$qrCodedata${widget.business.business_id}"); + Uri.encodeComponent("$qrCodedata${business.business_id}"); return "https://api.qrserver.com/v1/create-qr-code/?data=$encodedData&size=${qrSize}x${qrSize}&bgcolor=$bgColor&color=$color"; } Future saveImage(Uint8List imageBytes) async { final String filename = - "${widget.business.Name}_QR_Code_${DateTime.now().millisecondsSinceEpoch}.png"; + "${business.Name}_QR_Code_${DateTime.now().millisecondsSinceEpoch}.png"; if (kIsWeb) { await FileSaver.instance.saveFile( name: filename, @@ -241,7 +242,7 @@ class _MihBusinessQrCodeState extends State { ), FittedBox( child: Text( - widget.business.Name, + business.Name, style: TextStyle( fontSize: 35, fontWeight: FontWeight.bold, @@ -253,7 +254,7 @@ class _MihBusinessQrCodeState extends State { ), FittedBox( child: Text( - widget.business.type, + business.type, style: TextStyle( fontSize: 20, fontWeight: FontWeight.w600, @@ -335,9 +336,15 @@ class _MihBusinessQrCodeState extends State { @override void initState() { super.initState(); + MzansiProfileProvider profileProvider = + context.read(); + if (widget.business != null) { + business = widget.business!; + } else { + business = profileProvider.business!; + } _checkUserSession(); - futureImageUrl = - MihFileApi.getMinioFileUrl(widget.business.logo_path, context); + futureImageUrl = MihFileApi.getMinioFileUrl(business.logo_path, context); qrCodedata = "${AppEnviroment.baseAppUrl}/business-profile/view?business_id="; } @@ -418,8 +425,8 @@ class _MihBusinessQrCodeState extends State { onTap: () { shareMIHLink( context, - "Check out ${widget.business.Name} on the MIH app", - "$qrCodedata${widget.business.business_id}", + "Check out ${business.Name} on the MIH app", + "$qrCodedata${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 42f9f06a..f2f34dbd 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 @@ -5,12 +5,14 @@ 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_icons.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_review_business_window.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart'; +import 'package:provider/provider.dart'; class MihBusinessReviews extends StatefulWidget { - final Business business; + final Business? business; const MihBusinessReviews({ super.key, required this.business, @@ -21,15 +23,19 @@ class MihBusinessReviews extends StatefulWidget { } class _MihBusinessReviewsState extends State { - // late Future> _reviews; + late Business business; - // @override - // void initState() { - // super.initState(); - // _reviews = MihMzansiDirectoryServices().getAllReviewsofBusiness( - // widget.businessId, - // ); - // } + @override + void initState() { + super.initState(); + MzansiProfileProvider profileProvider = + context.read(); + if (widget.business != null) { + business = widget.business!; + } else { + business = profileProvider.business!; + } + } void onReviewTap(BusinessReview? businessReview, double width) { // showDialog(context: context, builder: (context)=> ) @@ -37,7 +43,7 @@ class _MihBusinessReviewsState extends State { context: context, builder: (context) { return MihReviewBusinessWindow( - business: widget.business, + business: business, businessReview: businessReview, screenWidth: width, readOnly: true, @@ -52,7 +58,7 @@ class _MihBusinessReviewsState extends State { double screenWidth = MediaQuery.of(context).size.width; return FutureBuilder( future: MihMzansiDirectoryServices().getAllReviewsofBusiness( - widget.business.business_id, + business.business_id, ), builder: (context, asyncSnapshot) { if (asyncSnapshot.connectionState == ConnectionState.waiting) { @@ -93,7 +99,7 @@ class _MihBusinessReviewsState extends State { ), const SizedBox(height: 10), Text( - "No reviews yet, be the first the review ${widget.business.Name}", + "No reviews yet, be the first the review ${business.Name}", textAlign: TextAlign.center, overflow: TextOverflow.visible, style: TextStyle( 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 c2bc32fb..b614dffb 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 @@ -36,11 +36,9 @@ class _MihBusinessUserSearchState extends State { void submitUserForm(MzansiProfileProvider profileProvider) { if (searchController.text != "") { - setState(() { - userSearch = searchController.text; - hasSearchedBefore = true; - userSearchResults = fetchUsers(profileProvider, userSearch); - }); + userSearch = searchController.text; + hasSearchedBefore = true; + userSearchResults = fetchUsers(profileProvider, userSearch); } } @@ -192,6 +190,7 @@ class _MihBusinessUserSearchState extends State { searchController.clear(); userSearch = ""; }); + profileProvider.setUserearchResults(userSearchResults: []); }, searchFocusNode: _searchFocusNode, ), 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 3dc774a9..4583f888 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 @@ -7,7 +7,6 @@ import 'package:mzansi_innovation_hub/mih_config/mih_colors.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:mzansi_innovation_hub/mih_services/mih_business_employee_services.dart'; import 'package:provider/provider.dart'; class MihMyBusinessTeam extends StatefulWidget { @@ -23,32 +22,11 @@ class _MihMyBusinessTeamState extends State { String errorCode = ""; String errorBody = ""; - 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'); - // } + // void getEmployeeData(MzansiProfileProvider mzansiProfileProvider) { + // WidgetsBinding.instance.addPostFrameCallback((_) async { + // await MihBusinessEmployeeServices() + // .fetchEmployees(mzansiProfileProvider, context); + // }); // } Widget displayEmployeeList(List employeeList) { @@ -89,7 +67,6 @@ class _MihMyBusinessTeamState extends State { builder: (BuildContext context, MzansiProfileProvider mzansiProfileProvider, Widget? child) { if (mzansiProfileProvider.employeeList == null) { - getEmployeeData(mzansiProfileProvider); return Center( child: Mihloadingcircle(), ); 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 8bc78d59..29049149 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 @@ -218,19 +218,17 @@ 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; - }); + 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 { 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 f44e7afb..7110a464 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 @@ -6,7 +6,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_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'; @@ -58,8 +57,12 @@ class _BuildLoyaltyCardListState extends State { ); } - void editCardWindow(MzansiProfileProvider mzansiProfileProvider, - BuildContext ctxt, int index, double width) { + void editCardWindow( + MzansiProfileProvider mzansiProfileProvider, + MzansiWalletProvider walletProvider, + BuildContext ctxt, + int index, + double width) { showDialog( context: context, barrierDismissible: false, @@ -144,6 +147,7 @@ class _BuildLoyaltyCardListState extends State { if (_formKey.currentState!.validate()) { int statusCode = await MIHMzansiWalletApis .updateLoyaltyCardAPICall( + walletProvider, mzansiProfileProvider.user!, widget.cardList[index].idloyalty_cards, widget.cardList[index].shop_name, @@ -211,7 +215,7 @@ class _BuildLoyaltyCardListState extends State { } void deleteCardWindow(MzansiProfileProvider mzansiProfileProvider, - BuildContext ctxt, int index) { + MzansiWalletProvider walletProvider, BuildContext ctxt, int index) { showDialog( context: context, barrierDismissible: false, @@ -221,6 +225,7 @@ class _BuildLoyaltyCardListState extends State { onTap: () async { int statusCode = await MIHMzansiWalletApis.deleteLoyaltyCardAPICall( + walletProvider, mzansiProfileProvider.user!, widget.cardList[index].idloyalty_cards, context, @@ -238,7 +243,7 @@ class _BuildLoyaltyCardListState extends State { } void addToFavCardWindow(MzansiProfileProvider mzansiProfileProvider, - BuildContext ctxt, int index) { + MzansiWalletProvider walletProvider, BuildContext ctxt, int index) { showDialog( context: context, barrierDismissible: false, @@ -270,6 +275,7 @@ class _BuildLoyaltyCardListState extends State { onPressed: () async { int statusCode = await MIHMzansiWalletApis.updateLoyaltyCardAPICall( + walletProvider, mzansiProfileProvider.user!, widget.cardList[index].idloyalty_cards, widget.cardList[index].shop_name, @@ -283,6 +289,7 @@ class _BuildLoyaltyCardListState extends State { context.pop(); context.pop(); await MIHMzansiWalletApis.getFavouriteLoyaltyCards( + walletProvider, mzansiProfileProvider.user!.app_id, context, ); @@ -323,7 +330,7 @@ class _BuildLoyaltyCardListState extends State { } void removeFromFavCardWindow(MzansiProfileProvider mzansiProfileProvider, - BuildContext ctxt, int index) { + MzansiWalletProvider walletProvider, BuildContext ctxt, int index) { showDialog( context: context, barrierDismissible: false, @@ -355,6 +362,7 @@ class _BuildLoyaltyCardListState extends State { onPressed: () async { int statusCode = await MIHMzansiWalletApis.updateLoyaltyCardAPICall( + walletProvider, mzansiProfileProvider.user!, widget.cardList[index].idloyalty_cards, widget.cardList[index].shop_name, @@ -368,6 +376,7 @@ class _BuildLoyaltyCardListState extends State { context.pop(); context.pop(); await MIHMzansiWalletApis.getFavouriteLoyaltyCards( + walletProvider, mzansiProfileProvider.user!.app_id, context, ); @@ -396,8 +405,8 @@ class _BuildLoyaltyCardListState extends State { ); } - void viewCardWindow( - MzansiProfileProvider mzansiProfileProvider, int index, double width) { + void viewCardWindow(MzansiProfileProvider mzansiProfileProvider, + MzansiWalletProvider walletProvider, 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++) { @@ -441,12 +450,14 @@ class _BuildLoyaltyCardListState extends State { if (widget.cardList[index].favourite == "") { addToFavCardWindow( mzansiProfileProvider, + walletProvider, context, index, ); } else { removeFromFavCardWindow( mzansiProfileProvider, + walletProvider, context, index, ); @@ -476,6 +487,7 @@ class _BuildLoyaltyCardListState extends State { }); editCardWindow( mzansiProfileProvider, + walletProvider, context, index, width, @@ -501,6 +513,7 @@ class _BuildLoyaltyCardListState extends State { onTap: () { deleteCardWindow( mzansiProfileProvider, + walletProvider, context, index, ); @@ -508,7 +521,6 @@ class _BuildLoyaltyCardListState extends State { ), ], onWindowTapClose: () { - context.read().loadBannerAd(); resetScreenBrightness(); context.pop(); }, @@ -570,9 +582,7 @@ class _BuildLoyaltyCardListState extends State { ), ), SizedBox(height: 10), - Consumer(builder: (context, bannerAdDisplay, child) { - return MihBannerAd(); - }), + MihBannerAd() // MihBannerAd(), ], ), @@ -705,9 +715,11 @@ class _BuildLoyaltyCardListState extends State { // final double width = size.width; //final double height = size.height; if (widget.cardList.isNotEmpty) { - return Consumer( + return Consumer2( builder: (BuildContext context, - MzansiProfileProvider mzansiProfileProvider, Widget? child) { + MzansiProfileProvider mzansiProfileProvider, + MzansiWalletProvider walletProvider, + Widget? child) { return GridView.builder( physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, @@ -732,6 +744,7 @@ class _BuildLoyaltyCardListState extends State { setScreenBrightness(1.0); viewCardWindow( mzansiProfileProvider, + walletProvider, 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 b1e69c35..d97ded85 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 @@ -10,6 +10,7 @@ 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_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_packages/mzansi_wallet/components/mih_card_display.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; @@ -72,9 +73,6 @@ class _MihAddCardWindowState extends State { child: MihButton( onPressed: () { context.pop(); - context.goNamed( - 'mzansiWallet', - ); }, buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), @@ -141,9 +139,11 @@ class _MihAddCardWindowState extends State { padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop" ? EdgeInsets.symmetric(horizontal: width * 0.05) : EdgeInsets.symmetric(horizontal: width * 0), - child: Consumer( + child: Consumer2( builder: (BuildContext context, - MzansiProfileProvider mzansiProfileProvider, Widget? child) { + MzansiProfileProvider mzansiProfileProvider, + MzansiWalletProvider walletProvider, + Widget? child) { return Column( children: [ MihForm( @@ -158,9 +158,7 @@ class _MihAddCardWindowState extends State { return MihValidationServices().isEmpty(value); }, requiredText: true, - dropdownOptions: const [ - "+More", - "Apple Tree", + dropdownOptions: const [ "+More", "Apple Tree", "Auchan", @@ -206,7 +204,7 @@ class _MihAddCardWindowState extends State { "Total Energies", "Toys R Us", "Woermann Brock", - "Woolworths" + "Woolworths", ], ), ValueListenableBuilder( @@ -306,6 +304,7 @@ class _MihAddCardWindowState extends State { } else { int statusCode = await MIHMzansiWalletApis .addLoyaltyCardAPICall( + walletProvider, mzansiProfileProvider.user!, mzansiProfileProvider.user!.app_id, _shopController.text, @@ -317,7 +316,7 @@ class _MihAddCardWindowState extends State { ); if (statusCode == 201) { context.pop(); - KenLogger.error("Card Added Successfully"); + KenLogger.success("Card Added Successfully"); successPopUp( "Successfully Added Card", "The loyalty card has been added to your favourites.", diff --git a/Frontend/lib/mih_packages/mzansi_wallet/mih_wallet.dart b/Frontend/lib/mih_packages/mzansi_wallet/mih_wallet.dart index bfc58d34..91ffcd41 100644 --- a/Frontend/lib/mih_packages/mzansi_wallet/mih_wallet.dart +++ b/Frontend/lib/mih_packages/mzansi_wallet/mih_wallet.dart @@ -3,7 +3,6 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ 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/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'; @@ -25,25 +24,31 @@ class _MihWalletState extends State { bool isLoading = true; Future setLoyaltyCards( - MzansiProfileProvider mzansiProfileProvider) async { + MzansiProfileProvider mzansiProfileProvider, + MzansiWalletProvider walletProvider, + ) async { await MIHMzansiWalletApis.getLoyaltyCards( - mzansiProfileProvider.user!.app_id, context); + walletProvider, mzansiProfileProvider.user!.app_id, context); } Future setFavouritesCards( - MzansiProfileProvider mzansiProfileProvider) async { + MzansiProfileProvider mzansiProfileProvider, + MzansiWalletProvider walletProvider, + ) async { await MIHMzansiWalletApis.getFavouriteLoyaltyCards( - mzansiProfileProvider.user!.app_id, context); + walletProvider, mzansiProfileProvider.user!.app_id, context); } @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) async { - var mzansiProfileProvider = context.read(); - await setLoyaltyCards(mzansiProfileProvider); - await setFavouritesCards(mzansiProfileProvider); - context.read().loadBannerAd(); + MzansiProfileProvider mzansiProfileProvider = + context.read(); + MzansiWalletProvider walletProvider = + context.read(); + await setLoyaltyCards(mzansiProfileProvider, walletProvider); + await setFavouritesCards(mzansiProfileProvider, walletProvider); setState(() { isLoading = false; }); @@ -89,7 +94,6 @@ class _MihWalletState extends State { temp[const Icon(Icons.favorite)] = () { context.read().setToolIndex(1); }; - return MihPackageTools( tools: temp, selcetedIndex: context.watch().toolIndex, 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 089a382d..65abd81b 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 @@ -29,19 +29,20 @@ class MihCards extends StatefulWidget { class _MihCardsState extends State { final TextEditingController cardSearchController = TextEditingController(); final FocusNode searchFocusNode = FocusNode(); - List listOfCards = []; final ValueNotifier> searchShopName = ValueNotifier([]); final MobileScannerController scannerController = MobileScannerController( detectionSpeed: DetectionSpeed.unrestricted, ); final boxFit = BoxFit.contain; + late MzansiWalletProvider _walletProvider; + late VoidCallback _searchListener; - void searchShop() { + void searchShop(List allCards) { if (cardSearchController.text.isEmpty) { - searchShopName.value = listOfCards; + searchShopName.value = allCards; } else { List temp = []; - for (var item in listOfCards) { + for (var item in allCards) { if (item.shop_name .toLowerCase() .contains(cardSearchController.text.toLowerCase()) || @@ -130,24 +131,21 @@ class _MihCardsState extends State { @override void dispose() { - cardSearchController.removeListener(searchShop); + cardSearchController.removeListener(_searchListener); cardSearchController.dispose(); searchShopName.dispose(); searchFocusNode.dispose(); super.dispose(); } - void getLoyaltyCards(BuildContext context) async { - setState(() { - listOfCards = context.read().loyaltyCards; - }); - searchShop(); - } - @override void initState() { - getLoyaltyCards(context); - cardSearchController.addListener(searchShop); + _walletProvider = context.read(); + _searchListener = () { + searchShop(_walletProvider.loyaltyCards); + }; + searchShopName.value = _walletProvider.loyaltyCards; + cardSearchController.addListener(_searchListener); super.initState(); } @@ -162,76 +160,89 @@ class _MihCardsState extends State { } Widget getBody(double width) { - return Stack( - children: [ - MihSingleChildScroll( - child: Column( - children: [ - Padding( - padding: EdgeInsets.symmetric(horizontal: width / 20), - child: MihSearchBar( - controller: cardSearchController, - hintText: "Search Cards", - // prefixIcon: Icons.search, - prefixIcon: Icons.search, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - hintColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onPrefixIconTap: () { - // print("Search Icon Pressed: ${cardSearchController.text}"); - }, - searchFocusNode: searchFocusNode, - ), - ), - const SizedBox(height: 10), - Consumer( - builder: (context, mzansiWalletProvider, child) { - listOfCards = mzansiWalletProvider.loyaltyCards; - return ValueListenableBuilder>( - valueListenable: searchShopName, - builder: (context, filteredCards, child) { - return BuildLoyaltyCardList( - cardList: filteredCards, //listOfCards, - navIndex: 0, - favouritesMode: false, - searchText: cardSearchController, - ); - }); - }, - ), - ], - ), - ), - Positioned( - right: 10, - bottom: 10, - child: MihFloatingMenu( - animatedIcon: AnimatedIcons.menu_close, - children: [ - SpeedDialChild( - child: Icon( - Icons.add, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + return Consumer( + builder: (BuildContext context, MzansiWalletProvider walletProvider, + Widget? child) { + if (cardSearchController.text.isEmpty) { + searchShopName.value = walletProvider.loyaltyCards; + } else { + // Re-run search with updated card list + searchShop(walletProvider.loyaltyCards); + } + return Stack( + children: [ + MihSingleChildScroll( + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: MihSearchBar( + controller: cardSearchController, + hintText: "Search Cards", + // prefixIcon: Icons.search, + prefixIcon: Icons.search, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + hintColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onPrefixIconTap: () { + // print("Search Icon Pressed: ${cardSearchController.text}"); + }, + searchFocusNode: searchFocusNode, + ), ), - 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, + const SizedBox(height: 10), + ValueListenableBuilder>( + valueListenable: searchShopName, + builder: (context, filteredCards, child) { + return BuildLoyaltyCardList( + cardList: filteredCards, //listOfCards, + navIndex: 0, + favouritesMode: false, + searchText: cardSearchController, + ); + }, ), - backgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onTap: () { - addCardWindow(context, width); - }, - ) - ]), - ) - ], + ], + ), + ), + Positioned( + right: 10, + bottom: 10, + 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, width); + }, + ) + ]), + ) + ], + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tiles/patient_profile_tile.dart b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tiles/patient_profile_tile.dart index 1fe19f93..e5722c52 100644 --- a/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tiles/patient_profile_tile.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/package_tiles/patient_profile_tile.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_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/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_patient_services.dart'; import 'package:provider/provider.dart'; class PatientProfileTile extends StatefulWidget { @@ -27,13 +29,24 @@ class _PatientProfileTileState extends State { Widget build(BuildContext context) { return MihPackageTile( authenticateUser: true, - onTap: () { + onTap: () async { PatientManagerProvider patientManagerProvider = context.read(); + MzansiProfileProvider profileProvider = + context.read(); + String? app_id = profileProvider.user!.app_id; + if (patientManagerProvider.selectedPatient == null) { + await MihPatientServices() + .getPatientDetails(app_id, patientManagerProvider); + } patientManagerProvider.setPersonalMode(true); - context.goNamed( - 'patientProfile', - ); + if (patientManagerProvider.selectedPatient != null) { + context.goNamed( + 'patientProfile', + ); + } else { + context.goNamed("patientProfileSetup"); + } // Navigator.of(context).pushNamed( // '/patient-profile', // arguments: widget.arguments, 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 index 3932042b..8477da3d 100644 --- 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 @@ -55,7 +55,7 @@ class _PatientClaimOrStatementState extends State { ], ), Visibility( - visible: patientManagerProvider.personalMode, + visible: !patientManagerProvider.personalMode, child: Positioned( right: 10, bottom: 10, 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 index 806ff6d7..3fced665 100644 --- a/Frontend/lib/mih_packages/patient_manager/pat_profile/patient_profile.dart +++ b/Frontend/lib/mih_packages/patient_manager/pat_profile/patient_profile.dart @@ -3,7 +3,6 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ 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'; @@ -30,19 +29,9 @@ class _PatientProfileState extends State { 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 { + if (patientManagerProvider.selectedPatient != null) { await MihPatientServices() .getPatientConsultationNotes(patientManagerProvider); await MihPatientServices().getPatientDocuments(patientManagerProvider); diff --git a/Frontend/lib/mih_services/mih_mzansi_directory_services.dart b/Frontend/lib/mih_services/mih_mzansi_directory_services.dart index 322615de..6b4bc076 100644 --- a/Frontend/lib/mih_services/mih_mzansi_directory_services.dart +++ b/Frontend/lib/mih_services/mih_mzansi_directory_services.dart @@ -166,7 +166,8 @@ class MihMzansiDirectoryServices { List favouriteBusinesses = List.from( l.map((model) => BookmarkedBusiness.fromJson(model))); - directoryProvider.setFavouriteBusinesses(businesses: favouriteBusinesses); + directoryProvider.setBookmarkedeBusinesses( + businesses: favouriteBusinesses); return favouriteBusinesses; } else if (response.statusCode == 404) { return []; diff --git a/Frontend/lib/mih_services/mih_mzansi_wallet_services.dart b/Frontend/lib/mih_services/mih_mzansi_wallet_services.dart index 7dcdd4e1..1acf927b 100644 --- a/Frontend/lib/mih_services/mih_mzansi_wallet_services.dart +++ b/Frontend/lib/mih_services/mih_mzansi_wallet_services.dart @@ -1,14 +1,13 @@ import 'dart:convert'; import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.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_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'; import '../mih_components/mih_pop_up_messages/mih_success_message.dart'; import '../mih_config/mih_env.dart'; @@ -17,6 +16,7 @@ class MIHMzansiWalletApis { final baseAPI = AppEnviroment.baseApiUrl; static Future getLoyaltyCards( + MzansiWalletProvider walletProvider, String app_id, BuildContext context, ) async { @@ -26,7 +26,7 @@ class MIHMzansiWalletApis { Iterable l = jsonDecode(response.body); List myCards = List.from( l.map((model) => MIHLoyaltyCard.fromJson(model))); - context.read().setLoyaltyCards(cards: myCards); + walletProvider.setLoyaltyCards(cards: myCards); // return myCards; } else { throw Exception('failed to fatch loyalty cards'); @@ -34,6 +34,7 @@ class MIHMzansiWalletApis { } static Future getFavouriteLoyaltyCards( + MzansiWalletProvider walletProvider, String app_id, BuildContext context, ) async { @@ -44,7 +45,7 @@ class MIHMzansiWalletApis { Iterable l = jsonDecode(response.body); List myCards = List.from( l.map((model) => MIHLoyaltyCard.fromJson(model))); - context.read().setFavouriteCards(cards: myCards); + walletProvider.setFavouriteCards(cards: myCards); } // else { // throw Exception('failed to fatch loyalty cards'); @@ -60,6 +61,7 @@ class MIHMzansiWalletApis { /// /// Returns VOID (TRIGGERS NOTIGICATIOPN ON SUCCESS) static Future deleteLoyaltyCardAPICall( + MzansiWalletProvider walletProvider, AppUser signedInUser, int idloyalty_cards, BuildContext context, @@ -77,9 +79,7 @@ class MIHMzansiWalletApis { //print(response.statusCode); context.pop(); if (response.statusCode == 200) { - context - .read() - .deleteLoyaltyCard(cardId: idloyalty_cards); + walletProvider.deleteLoyaltyCard(cardId: idloyalty_cards); } return response.statusCode; // if (response.statusCode == 200) { @@ -111,6 +111,7 @@ class MIHMzansiWalletApis { /// /// Returns VOID (TRIGGERS SUCCESS pop up) static Future addLoyaltyCardAPICall( + MzansiWalletProvider walletProvider, AppUser signedInUser, String app_id, String shop_name, @@ -137,6 +138,10 @@ class MIHMzansiWalletApis { }), ); context.pop(); + KenLogger.success("Response: $response"); + if (response.statusCode == 201) { + await getLoyaltyCards(walletProvider, app_id, context); + } return response.statusCode; // if (response.statusCode == 201) { // // Navigator.pop(context); @@ -164,6 +169,7 @@ class MIHMzansiWalletApis { /// /// Returns VOID (TRIGGERS NOTIGICATIOPN ON SUCCESS) static Future updateLoyaltyCardAPICall( + MzansiWalletProvider walletProvider, AppUser signedInUser, int idloyalty_cards, String shopName, @@ -190,17 +196,17 @@ 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, - ), - ); + walletProvider.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/pubspec.yaml b/Frontend/pubspec.yaml index 9969b895..7eee6769 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.2+99 +version: 1.2.2+103 # version: 1.1.1+97 #--- Updated version for upgrader package testing environment: