From 2e69e1dd92c46db24a7aa6afd5e8052d7165d7c2 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Mon, 20 Oct 2025 16:41:24 +0200 Subject: [PATCH] NEW: MIH Home & Mzansi Profile Provider Setup pt 2 done --- .../mih_circle_avatar.dart | 8 +- .../mih_image_display.dart | 31 +- .../mzansi_profile_provider.dart | 27 + Frontend/lib/mih_config/mih_go_router.dart | 5 +- .../about_mih/package_tools/mih_info.dart | 4 +- .../lib/mih_packages/mih_home/mih_home.dart | 123 +++-- .../package_tools/mih_business_home.dart | 282 +++++----- .../builders/build_employee_list.dart | 361 +------------ .../builders/build_user_list.dart | 347 ++----------- .../components/mih_add_employee_window.dart | 250 +++++++++ .../mih_edit_employee_details_window.dart | 319 ++++++++++++ .../mzansi_business_profile.dart | 80 +-- .../mzansi_set_up_business_profile.dart | 72 +++ .../mzansi_business_profile_tile.dart | 4 - .../mih_business_details_set_up.dart} | 487 +++++++++--------- .../package_tools/mih_business_qr_code.dart | 35 +- .../mih_business_user_search.dart | 16 - .../package_tools/mih_my_business_team.dart | 15 +- .../mih_edit_personal_profile_window.dart | 470 +++++++++++++++++ .../package_tools/mih_personal_profile.dart | 438 +--------------- .../mih_business_details_services.dart | 54 +- .../mih_business_employee_services.dart | 142 +++++ .../lib/mih_services/mih_file_services.dart | 6 +- .../mih_my_business_user_services.dart | 11 +- .../lib/mih_services/mih_user_services.dart | 3 + 25 files changed, 1937 insertions(+), 1653 deletions(-) create mode 100644 Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_add_employee_window.dart create mode 100644 Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_edit_employee_details_window.dart create mode 100644 Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_set_up_business_profile.dart rename Frontend/lib/mih_packages/mzansi_profile/business_profile/{profile_business_add.dart => package_tools/mih_business_details_set_up.dart} (81%) create mode 100644 Frontend/lib/mih_packages/mzansi_profile/personal_profile/components/mih_edit_personal_profile_window.dart create mode 100644 Frontend/lib/mih_services/mih_business_employee_services.dart diff --git a/Frontend/lib/mih_components/mih_package_components/mih_circle_avatar.dart b/Frontend/lib/mih_components/mih_package_components/mih_circle_avatar.dart index 4f0c3e71..c64aaa75 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_circle_avatar.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_circle_avatar.dart @@ -10,7 +10,7 @@ class MihCircleAvatar extends StatefulWidget { final ImageProvider? imageFile; final double width; final bool editable; - final TextEditingController fileNameController; + final TextEditingController? fileNameController; final onChange; final PlatformFile? userSelectedfile; final Color frameColor; @@ -130,7 +130,7 @@ class _MihCircleAvatarState extends State { }); setState(() { - widget.fileNameController.text = selectedFile.name; + widget.fileNameController!.text = selectedFile.name; }); } else { if (result != null) { @@ -148,7 +148,7 @@ class _MihCircleAvatarState extends State { }); setState(() { - widget.fileNameController.text = + widget.fileNameController!.text = file.path.split('/').last; }); } else { @@ -157,7 +157,7 @@ class _MihCircleAvatarState extends State { } } } catch (e) { - print("Error: $e"); + print("Here Error: $e"); } }, icon: Icon( diff --git a/Frontend/lib/mih_components/mih_package_components/mih_image_display.dart b/Frontend/lib/mih_components/mih_package_components/mih_image_display.dart index 6d6d3145..509fcc59 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_image_display.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_image_display.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; @@ -32,6 +33,7 @@ class _MihImageDisplayState extends State { late ImageProvider? imagePreview; ImageProvider? getImage() { + KenLogger.success(widget.imageFile.toString()); if (widget.imageFile == null) { return null; } else { @@ -58,13 +60,26 @@ class _MihImageDisplayState extends State { child: Stack( alignment: Alignment.center, children: [ - Visibility( - visible: imagePreview != null, - child: ClipRRect( - borderRadius: BorderRadius.circular(widget.width * 0.1), - child: Image(image: imagePreview!), - ), - ), + imagePreview != null + ? ClipRRect( + borderRadius: BorderRadius.circular(widget.width * 0.1), + child: Image(image: imagePreview!), + ) + : Container( + width: widget.width, + height: widget.height, + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + borderRadius: BorderRadius.circular(widget.width * 0.1), + ), + child: Icon( + Icons.image_not_supported_rounded, + size: widget.width * 0.3, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), Visibility( visible: widget.editable, child: Positioned( @@ -125,7 +140,7 @@ class _MihImageDisplayState extends State { } } } catch (e) { - print("Error: $e"); + print("here 2 Error: $e"); } }, icon: const Icon( diff --git a/Frontend/lib/mih_components/mih_providers/mzansi_profile_provider.dart b/Frontend/lib/mih_components/mih_providers/mzansi_profile_provider.dart index 8941a0a9..109aedf2 100644 --- a/Frontend/lib/mih_components/mih_providers/mzansi_profile_provider.dart +++ b/Frontend/lib/mih_components/mih_providers/mzansi_profile_provider.dart @@ -99,4 +99,31 @@ class MzansiProfileProvider extends ChangeNotifier { this.employeeList = employeeList; notifyListeners(); } + + void addLoyaltyCard({required BusinessEmployee newEmployee}) { + employeeList!.add(newEmployee); + notifyListeners(); + } + + void updateEmplyeeDetails({required BusinessEmployee updatedEmployee}) { + int index = employeeList!.indexWhere((employee) => + employee.business_id == updatedEmployee.business_id && + employee.app_id == updatedEmployee.app_id); + if (index != -1) { + employeeList![index] = updatedEmployee; + notifyListeners(); + } + } + + void deleteEmplyee({required BusinessEmployee deletedEmployee}) { + employeeList!.removeWhere((employee) => + employee.business_id == deletedEmployee.business_id && + employee.app_id == deletedEmployee.app_id); + notifyListeners(); + } + + void addEmployee({required BusinessEmployee newEmployee}) { + employeeList!.add(newEmployee); + notifyListeners(); + } } diff --git a/Frontend/lib/mih_config/mih_go_router.dart b/Frontend/lib/mih_config/mih_go_router.dart index 25743e6d..86211a8f 100644 --- a/Frontend/lib/mih_config/mih_go_router.dart +++ b/Frontend/lib/mih_config/mih_go_router.dart @@ -19,7 +19,7 @@ import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/mzansi_ai.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/mzansi_directory.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart'; -import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/profile_business_add.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/mzansi_set_up_business_profile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart'; import 'package:ken_logger/ken_logger.dart'; @@ -228,8 +228,7 @@ class MihGoRouter { path: MihGoRouterPaths.businessProfileSetup, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: businessProfileSetup"); - final AppUser? signedInUser = state.extra as AppUser?; - return ProfileBusinessAdd(signedInUser: signedInUser!); + return MzansiSetUpBusinessProfile(); }, ), // ========================== MIH Calculator ================================== diff --git a/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart b/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart index eccbbc4d..d3456a20 100644 --- a/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart +++ b/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart @@ -506,8 +506,8 @@ class _MihInfoState extends State { void shareMIHLink(BuildContext context, String message, String link) { String shareText = "$message: $link"; - Share.share( - shareText, + SharePlus.instance.share( + ShareParams(text: shareText), ); } diff --git a/Frontend/lib/mih_packages/mih_home/mih_home.dart b/Frontend/lib/mih_packages/mih_home/mih_home.dart index 61022390..92a4ea8a 100644 --- a/Frontend/lib/mih_packages/mih_home/mih_home.dart +++ b/Frontend/lib/mih_packages/mih_home/mih_home.dart @@ -39,7 +39,6 @@ class MihHome extends StatefulWidget { } class _MihHomeState extends State { - final proPicController = TextEditingController(); late int _selcetedIndex; late bool _personalHome; DateTime latestPrivacyPolicyDate = DateTime.parse("2024-12-01"); @@ -47,11 +46,30 @@ class _MihHomeState extends State { bool _isLoadingInitialData = true; Future _loadInitialData() async { + if (mounted) { + setState(() { + _isLoadingInitialData = true; + }); + } + MzansiProfileProvider mzansiProfileProvider = + context.read(); // Note: getUserData sets user and userProfilePicUrl in the provider - await getUserData(); + if (mzansiProfileProvider.user == null) { + await getUserData(); + } // Note: getUserConsentStatus sets userConsent in the provider - await getUserConsentStatus(); - await getBusinessData(); + if (mzansiProfileProvider.userConsent == null) { + await getUserConsentStatus(); + } + // 1. Get Business Data + if (mzansiProfileProvider.user != null && + mzansiProfileProvider.user!.type == "business" && + mzansiProfileProvider.business == null) { + KenLogger.success(mzansiProfileProvider.business == null + ? "Business is null, fetching business data..." + : "Business data already loaded."); + await getBusinessData(); + } // 2. Set state after all data is loaded if (mounted) { setState(() { @@ -61,13 +79,23 @@ class _MihHomeState extends State { } Future getBusinessData() async { - Business? business = context.read().business; AppUser? user = context.read().user; String logoUrl; String signatureUrl; - if (business == null && user!.type == "business") { + Business? responseBusiness = + await MihBusinessDetailsServices().getBusinessDetailsByUser(context); + if (responseBusiness == null && user!.type == "business") { + if (mounted) { + context.goNamed( + 'businessProfileSetup', + extra: user, + ); + } + } + + if (responseBusiness != null && user!.type == "business") { // Get Business - await MihBusinessDetailsServices().getBusinessDetailsByUser(context); + // Business Profile Set Up aleary logoUrl = await MihFileApi.getMinioFileUrl( context.read().business!.logo_path, context, @@ -152,10 +180,12 @@ class _MihHomeState extends State { } Future getUserData() async { + if (!mounted) return; String url; await MihUserServices().getUserDetails( context, ); + if (!mounted) return; url = await MihFileApi.getMinioFileUrl( context.read().user!.pro_pic_path, context, @@ -164,6 +194,7 @@ class _MihHomeState extends State { } Future getUserConsentStatus() async { + if (!mounted) return; await MihUserConsentServices().getUserConsentStatus(context); } @@ -175,9 +206,6 @@ class _MihHomeState extends State { @override void initState() { super.initState(); - WidgetsBinding.instance.addPostFrameCallback((_) async { - _loadInitialData(); - }); if (context.read().personalHome == true) { _selcetedIndex = 0; _personalHome = true; @@ -185,6 +213,7 @@ class _MihHomeState extends State { _selcetedIndex = 1; _personalHome = false; } + _loadInitialData(); } List getToolTitle() { @@ -211,28 +240,39 @@ class _MihHomeState extends State { // showPolicyWindow(mzansiProfileProvider.userConsent); return Stack( children: [ - MihPackage( - appActionButton: - getAction(mzansiProfileProvider.userProfilePicUrl as String), - appTools: - getTools(mzansiProfileProvider.user!.type != "personal"), - appBody: getToolBody(), - appToolTitles: getToolTitle(), - actionDrawer: getActionDrawer(), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - if (_selcetedIndex == 0) { - setState(() { - _selcetedIndex = newValue; - _personalHome = true; - }); - } else { - setState(() { - _selcetedIndex = newValue; - _personalHome = false; - }); - } + RefreshIndicator( + onRefresh: () async { + await _loadInitialData(); }, + child: SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: SizedBox( + height: MediaQuery.of(context).size.height, + child: MihPackage( + appActionButton: getAction( + mzansiProfileProvider.userProfilePicUrl as String), + appTools: getTools( + mzansiProfileProvider.user!.type != "personal"), + appBody: getToolBody(), + appToolTitles: getToolTitle(), + actionDrawer: getActionDrawer(), + selectedbodyIndex: _selcetedIndex, + onIndexChange: (newValue) { + if (_selcetedIndex == 0) { + setState(() { + _selcetedIndex = newValue; + _personalHome = true; + }); + } else { + setState(() { + _selcetedIndex = newValue; + _personalHome = false; + }); + } + }, + ), + ), + ), ), Visibility( visible: showPolicyWindow(mzansiProfileProvider.userConsent), @@ -443,7 +483,7 @@ class _MihHomeState extends State { imageFile: proPicUrl != "" ? NetworkImage(proPicUrl) : null, width: 50, editable: false, - fileNameController: proPicController, + fileNameController: null, userSelectedfile: null, // frameColor: frameColor, frameColor: MihColors.getSecondaryColor( @@ -452,17 +492,6 @@ class _MihHomeState extends State { MzansiInnovationHub.of(context)!.theme.mode == "Dark"), onChange: (_) {}, ), - // MIHProfilePicture( - // profilePictureFile: widget.propicFile, - // proPicController: proPicController, - // proPic: null, - // width: 45, - // radius: 21, - // drawerMode: false, - // editable: false, - // frameColor: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // onChange: (newProPic) {}, - // ), ), iconSize: 45, onTap: () { @@ -531,13 +560,7 @@ class _MihHomeState extends State { ); if (user.type != "personal") { toolBodies.add( - MihBusinessHome( - signedInUser: user, - personalSelected: _personalHome, - businessUser: businessUser, - business: business, - isBusinessUserNew: businessUser == null, - ), + MihBusinessHome(), ); } return toolBodies; diff --git a/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart b/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart index b9b1ae12..140544f2 100644 --- a/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart +++ b/Frontend/lib/mih_packages/mih_home/package_tools/mih_business_home.dart @@ -4,10 +4,9 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_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/about_mih/package_tile/about_mih_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tiles/mih_calculator_tile.dart'; @@ -18,20 +17,11 @@ import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profi import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_setup_business_profile_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/package_tiles/pat_manager_tile.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class MihBusinessHome extends StatefulWidget { - final AppUser signedInUser; - final bool personalSelected; - final Business? business; - final BusinessUser? businessUser; - final bool isBusinessUserNew; const MihBusinessHome({ super.key, - required this.signedInUser, - required this.personalSelected, - required this.business, - required this.businessUser, - required this.isBusinessUserNew, }); @override @@ -70,7 +60,7 @@ class _MihBusinessHomeState extends State List> temp = []; temp.add({ "Setup Business": MzansiSetupBusinessProfileTile( - signedInUser: widget.signedInUser, + signedInUser: context.read().user!, packageSize: packageSize, ) }); @@ -78,15 +68,17 @@ class _MihBusinessHomeState extends State } List> setBusinessPackages() { + MzansiProfileProvider mzansiProfileProvider = + context.read(); + if (mzansiProfileProvider.user == null || + mzansiProfileProvider.business == null || + mzansiProfileProvider.businessUser == null) { + return []; // Return empty list if data isn't ready + } List> temp = []; //=============== Biz Profile =============== temp.add({ "Business Profile": MzansiBusinessProfileTile( - arguments: BusinessArguments( - widget.signedInUser, - widget.businessUser, - widget.business, - ), packageSize: packageSize, ) }); @@ -94,10 +86,10 @@ class _MihBusinessHomeState extends State temp.add({ "Patient Manager": PatManagerTile( arguments: PatManagerArguments( - widget.signedInUser, + mzansiProfileProvider.user!, false, - widget.business, - widget.businessUser, + mzansiProfileProvider.business!, + mzansiProfileProvider.businessUser!, ), packageSize: packageSize, ) @@ -106,10 +98,10 @@ class _MihBusinessHomeState extends State temp.add({ "Calendar": MzansiCalendarTile( arguments: CalendarArguments( - widget.signedInUser, + mzansiProfileProvider.user!, false, - widget.business, - widget.businessUser, + mzansiProfileProvider.business!, + mzansiProfileProvider.businessUser!, ), packageSize: packageSize, ) @@ -124,7 +116,7 @@ class _MihBusinessHomeState extends State //=============== Calculator =============== temp.add({ "Calculator": MihCalculatorTile( - personalSelected: widget.personalSelected, + personalSelected: mzansiProfileProvider.personalHome, packageSize: packageSize, ) }); @@ -132,7 +124,7 @@ class _MihBusinessHomeState extends State temp.add({ "Mzansi AI": MzansiAiTile( arguments: MzansiAiArguments( - widget.signedInUser, + mzansiProfileProvider.user!, "", false, ), @@ -194,19 +186,11 @@ class _MihBusinessHomeState extends State void initState() { super.initState(); searchController.addListener(searchPackage); - if (widget.isBusinessUserNew) { - businessPackagesMap = setNewBusinessUserPackages(); - } else { + + WidgetsBinding.instance.addPostFrameCallback((_) { businessPackagesMap = setBusinessPackages(); - } - searchPackage(); - //Scrolling Banner message - // _marqueeController = AnimationController( - // vsync: this, - // duration: const Duration(seconds: 12), - // ); - // _scrollController = ScrollController(); - // WidgetsBinding.instance.addPostFrameCallback((_) => _startMarquee()); + searchPackage(); + }); } @override @@ -221,123 +205,113 @@ class _MihBusinessHomeState extends State } Widget getBody(double width, double height) { - return MihSingleChildScroll( - child: Column( - children: [ - // Icon( - // MihIcons.mihLogo, - // size: width / 2, - // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // const SizedBox(height: 10), - // Text( - // // "Welcome, ${widget.signedInUser.fname}!", - // "Mzansi Innovation Hub", - // textAlign: TextAlign.center, - // style: TextStyle( - // fontSize: 30, - // fontWeight: FontWeight.bold, - // color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // ), - // ), - // const SizedBox(height: 20), - Visibility( - visible: !widget.isBusinessUserNew, - child: Padding( - padding: EdgeInsets.symmetric(horizontal: width / 20), - child: MihSearchBar( - controller: searchController, - hintText: "Ask Mzansi", - prefixIcon: Icons.search, - prefixAltIcon: MihIcons.mzansiAi, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - hintColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onPrefixIconTap: () { - context.goNamed( - "mzansiAi", - extra: MzansiAiArguments( - widget.signedInUser, - searchController.text.isEmpty - ? null - : searchController.text, - false, - ), - ); - // Navigator.of(context).pushNamed( - // '/mzansi-ai', - // arguments: MzansiAiArguments( - // widget.signedInUser, - // searchController.text.isEmpty - // ? null - // : searchController.text, - // ), - // ); - searchController.clear(); - }, - searchFocusNode: _searchFocusNode, - ), - ), - ), - const SizedBox(height: 20), - ValueListenableBuilder( - valueListenable: searchPackageName, - builder: (context, value, child) { - List filteredPackages = value - .where((package) => package.keys.first - .toLowerCase() - .contains(searchController.text.toLowerCase())) - .map((package) => package.values.first) - .toList(); - if (filteredPackages.isNotEmpty) { - return GridView.builder( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - padding: getPadding(width, height), - // shrinkWrap: true, - itemCount: filteredPackages.length, - gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: packageSize, - crossAxisSpacing: 5, - ), - itemBuilder: (context, index) { - return filteredPackages[index]; - }, - ); - } else { - return Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 50), - Icon( - MihIcons.mzansiAi, - size: 165, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - const SizedBox(height: 10), - Text( - "Mzansi AI is here to help you!", - textAlign: TextAlign.center, - overflow: TextOverflow.visible, - style: TextStyle( - fontSize: 25, - fontWeight: FontWeight.bold, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + if (mzansiProfileProvider.business == null) { + return Center( + child: Mihloadingcircle(), + ); + } + return MihSingleChildScroll( + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: MihSearchBar( + controller: searchController, + hintText: "Ask Mzansi", + prefixIcon: Icons.search, + prefixAltIcon: MihIcons.mzansiAi, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + hintColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onPrefixIconTap: () { + context.goNamed( + "mzansiAi", + extra: MzansiAiArguments( + mzansiProfileProvider.user!, + searchController.text.isEmpty + ? null + : searchController.text, + false, ), - ), - ], - ); - } - }, + ); + // Navigator.of(context).pushNamed( + // '/mzansi-ai', + // arguments: MzansiAiArguments( + // widget.signedInUser, + // searchController.text.isEmpty + // ? null + // : searchController.text, + // ), + // ); + searchController.clear(); + }, + searchFocusNode: _searchFocusNode, + ), + ), + const SizedBox(height: 20), + ValueListenableBuilder( + valueListenable: searchPackageName, + builder: (context, value, child) { + List filteredPackages = value + .where((package) => package.keys.first + .toLowerCase() + .contains(searchController.text.toLowerCase())) + .map((package) => package.values.first) + .toList(); + if (filteredPackages.isNotEmpty) { + return GridView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + padding: getPadding(width, height), + // shrinkWrap: true, + itemCount: filteredPackages.length, + gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( + maxCrossAxisExtent: packageSize, + crossAxisSpacing: 5, + ), + itemBuilder: (context, index) { + return filteredPackages[index]; + }, + ); + } else { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.mzansiAi, + size: 165, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + const SizedBox(height: 10), + Text( + "Mzansi AI is here to help you!", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ], + ); + } + }, + ), + ], ), - ], - ), + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_employee_list.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_employee_list.dart index d4268a57..fa7fe96a 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_employee_list.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_employee_list.dart @@ -1,33 +1,15 @@ -import 'dart:convert'; - -import 'package:flutter_speed_dial/flutter_speed_dial.dart'; -import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_edit_employee_details_window.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:supertokens_flutter/http.dart' as http; class BuildEmployeeList extends StatefulWidget { - final List employees; - const BuildEmployeeList({ super.key, - required this.employees, }); @override @@ -35,339 +17,20 @@ class BuildEmployeeList extends StatefulWidget { } class _BuildEmployeeListState extends State { - TextEditingController accessController = TextEditingController(); - TextEditingController typeController = TextEditingController(); - TextEditingController fnameController = TextEditingController(); - TextEditingController lnameController = TextEditingController(); - - final _formKey = GlobalKey(); final baseAPI = AppEnviroment.baseApiUrl; - Future updateEmployeeAPICall(int index) async { - showDialog( - context: context, - builder: (context) { - return const Mihloadingcircle(); - }, - ); - - var response = await http.put( - Uri.parse("$baseAPI/business-user/employees/update/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "business_id": widget.employees[index].business_id, - "app_id": widget.employees[index].app_id, - "title": typeController.text, - "access": accessController.text, - }), - ); - if (response.statusCode == 200) { - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // //setState(() {}); - // Navigator.of(context).pushNamed( - // '/business-profile/manage', - // arguments: BusinessArguments( - // widget.arguments.signedInUser, - // widget.arguments.businessUser, - // widget.arguments.business, - // ), - // ); - String message = "Your employees details have been updated."; - successPopUp(message, false); - } else { - internetConnectionPopUp(); - } - } - - Future deleteNoteApiCall(int index) async { - var response = await http.delete( - Uri.parse("$baseAPI/business-user/employees/delete/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "business_id": widget.employees[index].business_id, - "app_id": widget.employees[index].app_id, - }), - ); - //print("Here4"); - //print(response.statusCode); - if (response.statusCode == 200) { - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pushNamed( - // '/business-profile/manage', - // arguments: BusinessArguments( - // widget.arguments.signedInUser, - // widget.arguments.businessUser, - // widget.arguments.business, - // ), - // ); - String message = - "The employee has been deleted successfully. This means they will no longer have access to your business profile"; - successPopUp(message, false); - } else { - internetConnectionPopUp(); - } - } - - void successPopUp(String message, bool stayOnPersonalSide) { - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.check_circle_outline_rounded, - size: 150, - color: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: "Successfully Updated Profile", - alertBody: Column( - children: [ - Text( - message, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 15, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 25), - Center( - child: MihButton( - onPressed: () { - context.goNamed( - 'mihHome', - extra: stayOnPersonalSide, - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - elevation: 10, - width: 300, - child: Text( - "Dismiss", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ) - ], - ), - alertColour: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - // return MIHSuccessMessage( - // successType: "Success", - // successMessage: message, - // ); - }, - ); - } - - void internetConnectionPopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); - } - - bool isRequiredFieldsCaptured() { - if (accessController.text.isEmpty || typeController.text.isEmpty) { - return false; - } else { - return true; - } - } - - void updateEmployeePopUp(int index, double width) { - setState(() { - accessController.text = widget.employees[index].access; - typeController.text = widget.employees[index].title; - fnameController.text = widget.employees[index].fname; - lnameController.text = widget.employees[index].lname; - }); + void updateEmployeePopUp(BusinessEmployee employee) { showDialog( context: context, barrierDismissible: false, - builder: (context) => MihPackageWindow( - fullscreen: false, - windowTitle: "Employee Details", - menuOptions: [ - SpeedDialChild( - child: Icon( - Icons.delete, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - label: "Delete Employee", - labelBackgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - labelStyle: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontWeight: FontWeight.bold, - ), - backgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - onTap: () { - showDeleteWarning(index); - }, - ), - ], - onWindowTapClose: () { - Navigator.pop(context); - }, - windowBody: Padding( - padding: - MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.05) - : const EdgeInsets.symmetric(horizontal: 0), - child: Column( - children: [ - MihForm( - formKey: _formKey, - formFields: [ - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: fnameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "First Name", - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: lnameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Surname", - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - controller: typeController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Title", - ), - // MihDropdownField( - // controller: typeController, - // hintText: "Title", - // dropdownOptions: const ["Doctor", "Assistant", "Other"], - // editable: true, - // enableSearch: true, - // validator: (value) { - // return MihValidationServices().isEmpty(value); - // }, - // requiredText: true, - // ), - const SizedBox(height: 10.0), - MihDropdownField( - controller: accessController, - hintText: "Access Type", - dropdownOptions: const ["Full", "Partial"], - editable: true, - enableSearch: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - requiredText: true, - ), - const SizedBox(height: 20.0), - Center( - child: MihButton( - onPressed: () { - if (_formKey.currentState!.validate()) { - if (isRequiredFieldsCaptured()) { - updateEmployeeAPICall(index); - } else { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage( - errorType: "Input Error"); - }, - ); - } - } else { - MihAlertServices().formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - width: 300, - child: Text( - "Update", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ], - ), - ), + builder: (context) => MihEditEmployeeDetailsWindow( + employee: employee, ), ); } - void showDeleteWarning(int index) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => MIHDeleteMessage( - deleteType: "Employee", - onTap: () { - deleteNoteApiCall(index); - })); - } - - @override - void dispose() { - accessController.dispose(); - typeController.dispose(); - fnameController.dispose(); - lnameController.dispose(); - super.dispose(); - } - @override Widget build(BuildContext context) { - double screenWidth = MediaQuery.of(context).size.width; return Consumer( builder: (BuildContext context, MzansiProfileProvider mzansiProfileProvider, Widget? child) { @@ -380,27 +43,29 @@ class _BuildEmployeeListState extends State { MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ); }, - itemCount: widget.employees.length, + itemCount: mzansiProfileProvider.employeeList!.length, itemBuilder: (context, index) { //final patient = widget.patients[index].id_no.contains(widget.searchString); //print(index); - var isMe = ""; + BusinessEmployee employee = + mzansiProfileProvider.employeeList![index]; + String isMe = ""; if (mzansiProfileProvider.user!.app_id == - widget.employees[index].app_id) { + mzansiProfileProvider.employeeList![index].app_id) { isMe = "(You)"; } return ListTile( title: Text( - "${widget.employees[index].fname} ${widget.employees[index].lname} - ${widget.employees[index].title} $isMe"), + "${mzansiProfileProvider.employeeList![index].fname} ${mzansiProfileProvider.employeeList![index].lname} - ${mzansiProfileProvider.employeeList![index].title} $isMe"), subtitle: Text( - "${widget.employees[index].username}\n${widget.employees[index].email}\nAccess: ${widget.employees[index].access}", + "${mzansiProfileProvider.employeeList![index].username}\n${mzansiProfileProvider.employeeList![index].email}\nAccess: ${mzansiProfileProvider.employeeList![index].access}", style: TextStyle( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), ), onTap: () { - updateEmployeePopUp(index, screenWidth); + updateEmployeePopUp(employee); }, ); }, diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart index c1c6e870..2bfa71d1 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart @@ -1,32 +1,18 @@ -import 'dart:convert'; - -import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_add_employee_window.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:flutter/material.dart'; -import 'package:supertokens_flutter/http.dart' as http; +import 'package:provider/provider.dart'; class BuildUserList extends StatefulWidget { final List users; - final BusinessArguments arguments; const BuildUserList({ super.key, required this.users, - required this.arguments, }); @override @@ -34,133 +20,8 @@ class BuildUserList extends StatefulWidget { } class _BuildUserListState extends State { - TextEditingController accessController = TextEditingController(); - TextEditingController typeController = TextEditingController(); - TextEditingController usernameController = TextEditingController(); - TextEditingController emailController = TextEditingController(); - - final _formKey = GlobalKey(); final baseAPI = AppEnviroment.baseApiUrl; - Future createBusinessUserAPICall(int index) async { - showDialog( - context: context, - builder: (context) { - return const Mihloadingcircle(); - }, - ); - var response = await http.post( - Uri.parse("$baseAPI/business-user/insert/"), - headers: { - "Content-Type": "application/json; charset=UTF-8" - }, - body: jsonEncode({ - "business_id": widget.arguments.business!.business_id, - "app_id": widget.users[index].app_id, - "signature": "", - "sig_path": "", - "title": "", - "access": accessController.text, - }), - ); - if (response.statusCode == 201) { - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pop(); - // Navigator.of(context).pushNamed( - // '/business-profile/manage', - // arguments: BusinessArguments( - // widget.arguments.signedInUser, - // widget.arguments.businessUser, - // widget.arguments.business, - // ), - // ); - String message = - "${widget.users[index].username} is now apart of your team with ${accessController.text} access to ${widget.arguments.business!.Name}"; - successPopUp(message, false); - } else { - internetConnectionPopUp(); - } - } - - void successPopUp(String message, bool stayOnPersonalSide) { - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.check_circle_outline_rounded, - size: 150, - color: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: "Successfully Updated Profile", - alertBody: Column( - children: [ - Text( - message, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 15, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 25), - Center( - child: MihButton( - onPressed: () { - context.goNamed( - 'mihHome', - extra: stayOnPersonalSide, - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - elevation: 10, - width: 300, - child: Text( - "Dismiss", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ) - ], - ), - alertColour: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - // return MIHSuccessMessage( - // successType: "Success", - // successMessage: message, - // ); - }, - ); - } - - bool isRequiredFieldsCaptured() { - if (accessController.text.isEmpty) { - return false; - } else { - return true; - } - } - - void internetConnectionPopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); - } - String hideEmail(String email) { var firstLetter = email[0]; var end = email.split("@")[1]; @@ -168,180 +29,50 @@ class _BuildUserListState extends State { } void addEmployeePopUp(int index, double width) { - setState(() { - //accessController.text = widget.users[index].access; - //typeController.text = widget.users[index].title; - // var fnameInitial = widget.users[index].fname[0]; - // var lnameInitial = widget.users[index].lname[0]; - usernameController.text = widget.users[index].username; - emailController.text = hideEmail(widget.users[index].email); - }); showDialog( - context: context, - barrierDismissible: false, - builder: (context) => MihPackageWindow( - fullscreen: false, - windowTitle: "Add Employee", - windowBody: Padding( - padding: - MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.05) - : const EdgeInsets.symmetric(horizontal: 0), - child: Column( - children: [ - MihForm( - formKey: _formKey, - formFields: [ - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: usernameController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Username", - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: emailController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Email", - ), - const SizedBox(height: 10.0), - // MihTextFormField( - // fillColor: MihColors.getSecondaryColor( - // MzansiInnovationHub.of(context)!.theme.mode == - // "Dark"), - // inputColor: MihColors.getPrimaryColor( - // MzansiInnovationHub.of(context)!.theme.mode == - // "Dark"), - // controller: typeController, - // multiLineInput: false, - // requiredText: true, - // readOnly: true, - // hintText: "Title", - // ), - // MihDropdownField( - // controller: typeController, - // hintText: "Title", - // dropdownOptions: const ["Doctor", "Assistant", "Other"], - // editable: true, - // enableSearch: true, - // validator: (value) { - // return MihValidationServices().isEmpty(value); - // }, - // requiredText: true, - // ), - // const SizedBox(height: 10.0), - MihDropdownField( - controller: accessController, - hintText: "Access Type", - dropdownOptions: const ["Full", "Partial"], - editable: true, - enableSearch: true, - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - requiredText: true, - ), - const SizedBox(height: 15.0), - Center( - child: MihButton( - onPressed: () { - if (_formKey.currentState!.validate()) { - if (isRequiredFieldsCaptured()) { - createBusinessUserAPICall(index); - } else { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage( - errorType: "Input Error"); - }, - ); - } - } else { - MihAlertServices() - .formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - width: 300, - child: Text( - "Add", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ], - ), - ), - onWindowTapClose: () { - Navigator.pop(context); - })); - } - - @override - void dispose() { - accessController.dispose(); - typeController.dispose(); - usernameController.dispose(); - emailController.dispose(); - super.dispose(); + context: context, + barrierDismissible: false, + builder: (context) => MihAddEmployeeWindow( + user: widget.users[index], + ), + ); } @override Widget build(BuildContext context) { double screenWidth = MediaQuery.of(context).size.width; - return ListView.separated( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - separatorBuilder: (BuildContext context, index) { - return Divider( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - }, - itemCount: widget.users.length, - itemBuilder: (context, index) { - var isYou = ""; - if (widget.arguments.signedInUser.app_id == - widget.users[index].app_id) { - isYou = "(You)"; - } - return ListTile( - title: Text("@${widget.users[index].username} $isYou"), - subtitle: Text( - "Email: ${hideEmail(widget.users[index].email)}", - style: TextStyle( + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + separatorBuilder: (BuildContext context, index) { + return Divider( color: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - onTap: () { - addEmployeePopUp(index, screenWidth); + ); + }, + itemCount: widget.users.length, + itemBuilder: (context, index) { + var isYou = ""; + if (mzansiProfileProvider.user!.app_id == + widget.users[index].app_id) { + isYou = "(You)"; + } + return ListTile( + title: Text("@${widget.users[index].username} $isYou"), + subtitle: Text( + "Email: ${hideEmail(widget.users[index].email)}", + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + onTap: () { + addEmployeePopUp(index, screenWidth); + }, + ); }, ); }, diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_add_employee_window.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_add_employee_window.dart new file mode 100644 index 00000000..daf43813 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_add_employee_window.dart @@ -0,0 +1,250 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_employee_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; + +class MihAddEmployeeWindow extends StatefulWidget { + final AppUser user; + const MihAddEmployeeWindow({ + super.key, + required this.user, + }); + + @override + State createState() => _MihAddEmployeeWindowState(); +} + +class _MihAddEmployeeWindowState extends State { + TextEditingController accessController = TextEditingController(); + TextEditingController usernameController = TextEditingController(); + TextEditingController emailController = TextEditingController(); + final _formKey = GlobalKey(); + + Future createBusinessUserAPICall( + MzansiProfileProvider mzansiProfileProvider) async { + int statusCode = await MihBusinessEmployeeServices().addEmployee( + mzansiProfileProvider, + widget.user, + accessController.text, + context, + ); + if (statusCode == 201) { + String message = + "${widget.user.username} is now apart of your team with ${accessController.text} access to ${mzansiProfileProvider.business!.Name}"; + successPopUp(message, false); + } else { + internetConnectionPopUp(); + } + } + + void successPopUp(String message, bool stayOnPersonalSide) { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.check_circle_outline_rounded, + size: 150, + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: "Successfully Updated Profile", + alertBody: Column( + children: [ + Text( + message, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + context.pop(); + context.pop(); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Dismiss", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + // return MIHSuccessMessage( + // successType: "Success", + // successMessage: message, + // ); + }, + ); + } + + void internetConnectionPopUp() { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Internet Connection"); + }, + ); + } + + bool isRequiredFieldsCaptured() { + if (accessController.text.isEmpty) { + return false; + } else { + return true; + } + } + + @override + void dispose() { + super.dispose(); + accessController.dispose(); + usernameController.dispose(); + emailController.dispose(); + } + + @override + void initState() { + super.initState(); + usernameController.text = widget.user.username; + emailController.text = widget.user.email; + } + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return MihPackageWindow( + fullscreen: false, + windowTitle: "Add Employee", + windowBody: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: screenWidth * 0.05) + : const EdgeInsets.symmetric(horizontal: 0), + child: Column( + children: [ + MihForm( + formKey: _formKey, + formFields: [ + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: usernameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Username", + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: emailController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Email", + ), + const SizedBox(height: 10.0), + MihDropdownField( + controller: accessController, + hintText: "Access Type", + dropdownOptions: const ["Full", "Partial"], + editable: true, + enableSearch: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + requiredText: true, + ), + const SizedBox(height: 15.0), + Center( + child: MihButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + if (isRequiredFieldsCaptured()) { + createBusinessUserAPICall(mzansiProfileProvider); + } else { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage( + errorType: "Input Error"); + }, + ); + } + } else { + MihAlertServices().formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Add", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ], + ), + ), + onWindowTapClose: () { + Navigator.pop(context); + }, + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_edit_employee_details_window.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_edit_employee_details_window.dart new file mode 100644 index 00000000..0b2bd362 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_edit_employee_details_window.dart @@ -0,0 +1,319 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_speed_dial/flutter_speed_dial.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_employee_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; + +class MihEditEmployeeDetailsWindow extends StatefulWidget { + final BusinessEmployee employee; + const MihEditEmployeeDetailsWindow({ + super.key, + required this.employee, + }); + + @override + State createState() => + _MihEditEmployeeDetailsWindowState(); +} + +class _MihEditEmployeeDetailsWindowState + extends State { + TextEditingController accessController = TextEditingController(); + TextEditingController titleController = TextEditingController(); + TextEditingController fnameController = TextEditingController(); + TextEditingController lnameController = TextEditingController(); + final _formKey = GlobalKey(); + + void updateEmployeeAPICall( + MzansiProfileProvider mzansiProfileProvider) async { + int statusCode = await MihBusinessEmployeeServices().updateEmployeeDetails( + mzansiProfileProvider, + widget.employee, + titleController.text, + accessController.text, + context); + if (statusCode == 200) { + String message = "Your employees details have been updated."; + successPopUp(message, false); + } else { + internetConnectionPopUp(); + } + } + + Future deleteNoteApiCall() async { + int statusCode = await MihBusinessEmployeeServices().deleteEmployee( + context.read(), + widget.employee, + context, + ); + if (statusCode == 200) { + String message = + "The employee has been deleted successfully. This means they will no longer have access to your business profile"; + successPopUp(message, false); + } else { + internetConnectionPopUp(); + } + } + + void showDeleteWarning() { + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => MIHDeleteMessage( + deleteType: "Employee", + onTap: () { + deleteNoteApiCall(); + })); + } + + void successPopUp(String message, bool stayOnPersonalSide) { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.check_circle_outline_rounded, + size: 150, + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: "Successfully Updated Profile", + alertBody: Column( + children: [ + Text( + message, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + context.pop(); + context.pop(); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Dismiss", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + // return MIHSuccessMessage( + // successType: "Success", + // successMessage: message, + // ); + }, + ); + } + + void internetConnectionPopUp() { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Internet Connection"); + }, + ); + } + + bool isRequiredFieldsCaptured() { + if (accessController.text.isEmpty || titleController.text.isEmpty) { + return false; + } else { + return true; + } + } + + @override + void dispose() { + accessController.dispose(); + titleController.dispose(); + fnameController.dispose(); + lnameController.dispose(); + super.dispose(); + } + + @override + void initState() { + super.initState(); + fnameController.text = widget.employee.fname; + lnameController.text = widget.employee.lname; + titleController.text = widget.employee.title; + accessController.text = widget.employee.access; + } + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return MihPackageWindow( + fullscreen: false, + windowTitle: "Employee Details", + menuOptions: [ + SpeedDialChild( + child: Icon( + Icons.delete, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + label: "Delete Employee", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onTap: () { + showDeleteWarning(); + }, + ), + ], + onWindowTapClose: () { + Navigator.pop(context); + }, + windowBody: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: screenWidth * 0.05) + : const EdgeInsets.symmetric(horizontal: 0), + child: Column( + children: [ + MihForm( + formKey: _formKey, + formFields: [ + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: fnameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "First Name", + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: lnameController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Surname", + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: titleController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Title", + ), + const SizedBox(height: 10.0), + MihDropdownField( + controller: accessController, + hintText: "Access Type", + dropdownOptions: const ["Full", "Partial"], + editable: true, + enableSearch: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + requiredText: true, + ), + const SizedBox(height: 20.0), + Center( + child: MihButton( + onPressed: () { + if (_formKey.currentState!.validate()) { + if (isRequiredFieldsCaptured()) { + updateEmployeeAPICall(mzansiProfileProvider); + } else { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage( + errorType: "Input Error"); + }, + ); + } + } else { + MihAlertServices().formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Update", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart index 1baef840..de297b57 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart @@ -1,18 +1,16 @@ -import 'dart:convert'; - import 'package:go_router/go_router.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_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_config/mih_env.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:provider/provider.dart'; -import 'package:supertokens_flutter/http.dart' as http; class MzansiBusinessProfile extends StatefulWidget { const MzansiBusinessProfile({ @@ -24,40 +22,6 @@ class MzansiBusinessProfile extends StatefulWidget { } class _MzansiBusinessProfileState extends State { - String errorCode = ""; - String errorBody = ""; - - Future fetchEmployees() async { - //print("Patien manager page: $endpoint"); - MzansiProfileProvider mzansiProfileProvider = - context.read(); - 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'); - } - } - - @override - void initState() { - super.initState(); - WidgetsBinding.instance.addPostFrameCallback((_) async { - await fetchEmployees(); - }); - } - @override Widget build(BuildContext context) { return MihPackage( @@ -82,6 +46,7 @@ class _MzansiBusinessProfileState extends State { extra: false, ); FocusScope.of(context).unfocus(); + context.read().setBusinessIndex(0); }, ); } @@ -97,15 +62,15 @@ class _MzansiBusinessProfileState extends State { temp[const Icon(Icons.people)] = () { context.read().setBusinessIndex(2); }; - // temp[const Icon(Icons.add)] = () { - // context.read().setBusinessIndex(3); - // }; - // temp[const Icon(Icons.star_rate_rounded)] = () { - // context.read().setBusinessIndex(4); - // }; - // temp[const Icon(Icons.qr_code_rounded)] = () { - // context.read().setBusinessIndex(5); - // }; + temp[const Icon(Icons.add)] = () { + context.read().setBusinessIndex(3); + }; + temp[const Icon(Icons.star_rate_rounded)] = () { + context.read().setBusinessIndex(4); + }; + temp[const Icon(Icons.qr_code_rounded)] = () { + context.read().setBusinessIndex(5); + }; return MihPackageTools( tools: temp, selcetedIndex: context.watch().businessIndex, @@ -117,12 +82,13 @@ class _MzansiBusinessProfileState extends State { MihBusinessDetails(), MihMyBusinessUser(), MihMyBusinessTeam(), - // MihBusinessUserSearch(arguments: widget.arguments), - // MihBusinessReviews(business: widget.arguments.business!), - // MihBusinessQrCode( - // business: widget.arguments.business!, - // startUpSearch: "", - // ), + MihBusinessUserSearch(), + MihBusinessReviews( + business: context.watch().business!), + MihBusinessQrCode( + business: context.watch().business!, + startUpSearch: "", + ), ]; return toolBodies; } @@ -132,9 +98,9 @@ class _MzansiBusinessProfileState extends State { "Profile", "User", "Team", - // "Add", - // "Reviews", - // "Share", + "Add", + "Reviews", + "Share", ]; return toolTitles; } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_set_up_business_profile.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_set_up_business_profile.dart new file mode 100644 index 00000000..4449a393 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_set_up_business_profile.dart @@ -0,0 +1,72 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_set_up.dart'; +import 'package:provider/provider.dart'; + +class MzansiSetUpBusinessProfile extends StatefulWidget { + const MzansiSetUpBusinessProfile({super.key}); + + @override + State createState() => + _MzansiSetUpBusinessProfileState(); +} + +class _MzansiSetUpBusinessProfileState + extends State { + @override + Widget build(BuildContext context) { + return MihPackage( + appActionButton: getAction(), + appTools: getTools(), + appBody: getToolBody(), + appToolTitles: getToolTitle(), + selectedbodyIndex: context.watch().businessIndex, + onIndexChange: (newIndex) { + context.read().setBusinessIndex(newIndex); + }, + ); + } + + MihPackageAction getAction() { + return MihPackageAction( + icon: const Icon(Icons.arrow_back), + iconSize: 35, + onTap: () { + context.goNamed( + 'mihHome', + ); + FocusScope.of(context).unfocus(); + context.read().setBusinessIndex(0); + }, + ); + } + + MihPackageTools getTools() { + Map temp = {}; + temp[const Icon(Icons.business)] = () { + context.read().setBusinessIndex(0); + }; + return MihPackageTools( + tools: temp, + selcetedIndex: context.watch().businessIndex, + ); + } + + List getToolTitle() { + List toolTitles = [ + "Set Up Profile", + ]; + return toolTitles; + } + + List getToolBody() { + List toolBodies = [ + MihBusinessDetailsSetUp(), + ]; + return toolBodies; + } +} diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart index abd349c7..96d782bf 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart @@ -2,16 +2,13 @@ import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; class MzansiBusinessProfileTile extends StatefulWidget { - final BusinessArguments arguments; final double packageSize; const MzansiBusinessProfileTile({ super.key, - required this.arguments, required this.packageSize, }); @@ -27,7 +24,6 @@ class _MzansiBusinessProfileTileState extends State { onTap: () { context.goNamed( "businessProfileManage", - extra: widget.arguments, ); // Navigator.of(context).pushNamed( // '/business-profile/manage', diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_set_up.dart similarity index 81% rename from Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart rename to Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_set_up.dart index 550d5fd0..ab37bd22 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_set_up.dart @@ -1,53 +1,43 @@ -import 'dart:convert'; - import 'package:country_code_picker/country_code_picker.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; import 'package:http/http.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_image_display.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_my_business_user_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_action.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_body.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_header.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_layout_builder.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:file_picker/file_picker.dart'; +import 'package:provider/provider.dart'; -class ProfileBusinessAdd extends StatefulWidget { - //final BusinessUserScreenArguments arguments; - final AppUser signedInUser; - const ProfileBusinessAdd({ - super.key, - required this.signedInUser, - }); +class MihBusinessDetailsSetUp extends StatefulWidget { + const MihBusinessDetailsSetUp({super.key}); @override - State createState() => _ProfileBusinessAddState(); + State createState() => + _MihBusinessDetailsSetUpState(); } -class _ProfileBusinessAddState extends State { - final FocusNode _focusNode = FocusNode(); - final baseAPI = AppEnviroment.baseApiUrl; - +class _MihBusinessDetailsSetUpState extends State { final nameController = TextEditingController(); final typeController = TextEditingController(); final regController = TextEditingController(); final addressController = TextEditingController(); - final logonameController = TextEditingController(); final fnameController = TextEditingController(); final lnameController = TextEditingController(); final titleController = TextEditingController(); @@ -62,65 +52,33 @@ class _ProfileBusinessAddState extends State { final websiteController = TextEditingController(); final ratingController = TextEditingController(); final missionVisionController = TextEditingController(); - - ImageProvider? logoPreview; - ImageProvider? signaturePreview; - PlatformFile? selectedLogo; - PlatformFile? selectedSignature; - + final logoFileNameController = TextEditingController(); + PlatformFile? newSelectedLogoPic; + PlatformFile? newSelectedSignaturePic; + final FocusNode _focusNode = FocusNode(); + final _formKey = GlobalKey(); final ValueNotifier _counter = ValueNotifier(0); final ValueNotifier busType = ValueNotifier(""); - final _formKey = GlobalKey(); late String env; - Future uploadFile(String id, PlatformFile? selectedFile) async { - print("Inside uploud file method"); - int uploadStatusCode = 0; - uploadStatusCode = await MihFileApi.uploadFile( - id, - env, - "business_files", - selectedFile, - context, - ); - print("Status code: $uploadStatusCode"); - if (uploadStatusCode == 200) { - return true; + void submitForm(MzansiProfileProvider mzansiProfileProvider) { + if (isFieldsFilled()) { + createBusinessProfileAPICall(mzansiProfileProvider); } else { - return false; + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Input Error"); + }, + ); } } - Future createBusinessUserAPICall(String business_id) async { - print("Inside create bus user method"); - int statusCode = await MihMyBusinessUserServices().createBusinessUser( - business_id, - widget.signedInUser.app_id, - signtureController.text, - titleController.text, - accessController.text, - context, - ); - print("Status code: $statusCode"); - if (statusCode == 201) { - // Navigator.of(context).pop(); - // Navigator.of(context).popAndPushNamed( - // '/', - // arguments: AuthArguments(false, false), - // ); - String message = - "Your business profile is now live! You can now start connecting with customers and growing your business."; - successPopUp(message, false); - } else { - internetConnectionPopUp(); - } - } - - Future createBusinessProfileAPICall() async { - print("Inside create business profile method"); + Future createBusinessProfileAPICall( + MzansiProfileProvider mzansiProfileProvider) async { Response response = await MihBusinessDetailsServices().createBusinessDetails( - widget.signedInUser.app_id, + mzansiProfileProvider, nameController.text, typeController.text, regController.text, @@ -128,23 +86,87 @@ class _ProfileBusinessAddState extends State { vatNoController.text, emailController.text, getNumberWithCountryCode(), - // "${countryCodeController.text}-${contactController.text}", locationController.text, - logonameController.text, + logoFileNameController.text, websiteController.text, "0", missionVisionController.text, context, ); - print(response.body); if (response.statusCode == 201) { - var businessResponse = jsonDecode(response.body); - createBusinessUserAPICall(businessResponse['business_id']); + bool successUpload = + await uploadFile(mzansiProfileProvider, newSelectedLogoPic); + if (successUpload) { + String logoUrl = await MihFileApi.getMinioFileUrl( + mzansiProfileProvider.business!.logo_path, context); + mzansiProfileProvider.setBusinessProfilePicUrl(logoUrl); + } + await createBusinessUserAPICall(mzansiProfileProvider); } else { internetConnectionPopUp(); } } + Future createBusinessUserAPICall( + MzansiProfileProvider mzansiProfileProvider) async { + int statusCode = await MihMyBusinessUserServices().createBusinessUser( + mzansiProfileProvider.business!.business_id, + mzansiProfileProvider.user!.app_id, + signtureController.text, + titleController.text, + accessController.text, + mzansiProfileProvider, + context, + ); + if (statusCode == 201) { + bool successUpload = + await uploadFile(mzansiProfileProvider, newSelectedSignaturePic); + if (successUpload) { + String sigUrl = await MihFileApi.getMinioFileUrl( + mzansiProfileProvider.businessUser!.sig_path, context); + mzansiProfileProvider.setBusinessUserSignatureUrl(sigUrl); + String message = + "Your business profile is now live! You can now start connecting with customers and growing your business."; + successPopUp(message, false); + } else { + internetConnectionPopUp(); + } + } else { + internetConnectionPopUp(); + } + } + + Future uploadFile( + MzansiProfileProvider mzansiProfileProvider, PlatformFile? image) async { + if (newSelectedLogoPic != null) { + int uploadStatusCode = 0; + uploadStatusCode = await MihFileApi.uploadFile( + mzansiProfileProvider.business!.business_id, + env, + "business_files", + image, + context, + ); + if (uploadStatusCode == 200) { + return true; + } else { + return false; + } + } else { + return true; // No file selected, so no upload needed + } + } + + bool isFieldsFilled() { + if (typeController.text.isEmpty || + titleController.text.isEmpty || + accessController.text.isEmpty) { + return false; + } else { + return true; + } + } + String getNumberWithCountryCode() { String numberWithoutBeginingZero = ""; if (contactController.text[0] == "0") { @@ -157,13 +179,22 @@ class _ProfileBusinessAddState extends State { return "${countryCodeController.text}-$numberWithoutBeginingZero"; } - void internetConnectionPopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); + Color getMissionVisionLimitColor(int limit) { + if (_counter.value <= limit) { + return MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } else { + return MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } + } + + void typeSelected() { + if (typeController.text.isNotEmpty) { + busType.value = typeController.text; + } else { + busType.value = ""; + } } void successPopUp(String message, bool stayOnPersonalSide) { @@ -227,110 +258,90 @@ class _ProfileBusinessAddState extends State { ); } - bool isFieldsFilled() { - if (typeController.text.isEmpty || - titleController.text.isEmpty || - accessController.text.isEmpty) { - return false; - } else { - return true; - } - } - - void submitForm() { - if (isFieldsFilled()) { - print("Inside submit method"); - createBusinessProfileAPICall(); - } else { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Input Error"); - }, - ); - } - } - - void emailError() { + void internetConnectionPopUp() { showDialog( context: context, builder: (context) { - return const MIHErrorMessage(errorType: "Invalid Email"); + return const MIHErrorMessage(errorType: "Internet Connection"); }, ); } - bool isEmailValid() { - String text = emailController.text; - var regex = RegExp(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'); - return regex.hasMatch(text); - } - - // bool validEmail() { - // String text = emailController.text; - // var regex = RegExp(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$'); - // return regex.hasMatch(text); - // } - - void typeSelected() { - if (typeController.text.isNotEmpty) { - busType.value = typeController.text; + void initialiseControlers(MzansiProfileProvider mzansiProfileProvider) { + typeController.addListener(typeSelected); + setState(() { + fnameController.text = mzansiProfileProvider.user!.fname; + lnameController.text = mzansiProfileProvider.user!.lname; + accessController.text = "Full"; + countryCodeController.text = "+27"; + }); + if (AppEnviroment.getEnv() == "Prod") { + env = "Prod"; } else { - busType.value = ""; + env = "Dev"; } + missionVisionController.addListener(() { + setState(() { + _counter.value = missionVisionController.text.characters.length; + }); + }); } - MIHAction getActionButton() { - return MIHAction( - icon: const Icon(Icons.arrow_back), - iconSize: 35, - onTap: () { - // Navigator.of(context).pop(); - context.goNamed( - 'mihHome', - extra: true, - ); - }, - ); + @override + void dispose() { + typeController.removeListener(typeSelected); + nameController.dispose(); + typeController.dispose(); + regController.dispose(); + addressController.dispose(); + fnameController.dispose(); + lnameController.dispose(); + titleController.dispose(); + signtureController.dispose(); + accessController.dispose(); + countryCodeController.dispose(); + contactController.dispose(); + emailController.dispose(); + locationController.dispose(); + practiceNoController.dispose(); + vatNoController.dispose(); + websiteController.dispose(); + ratingController.dispose(); + missionVisionController.dispose(); + logoFileNameController.dispose(); + busType.dispose(); + _focusNode.dispose(); + _counter.dispose(); + super.dispose(); } - MIHHeader getHeader() { - return const MIHHeader( - headerAlignment: MainAxisAlignment.center, - headerItems: [ - Text( - "Set Up Business Profile", - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 25, - ), - ), - ], - ); + @override + void initState() { + super.initState(); + initialiseControlers(context.read()); } - Color getMissionVisionLimitColor(int limit) { - if (_counter.value <= limit) { - return MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"); - } else { - return MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"); - } - } - - MIHBody getBody(double width) { - return MIHBody( + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return MihPackageToolBody( borderOn: false, - bodyItems: [ - KeyboardListener( + bodyItem: getBody(screenWidth), + ); + } + + Widget getBody(double width) { + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return KeyboardListener( focusNode: _focusNode, autofocus: true, onKeyEvent: (event) async { if (event is KeyDownEvent && event.logicalKey == LogicalKeyboardKey.enter) { if (_formKey.currentState!.validate()) { - submitForm(); + submitForm(mzansiProfileProvider); } else { MihAlertServices().formNotFilledCompletely(context); } @@ -345,7 +356,7 @@ class _ProfileBusinessAddState extends State { child: Column( children: [ const Text( - "My Business Details", + "Business Details", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 25, @@ -359,6 +370,29 @@ class _ProfileBusinessAddState extends State { MihForm( formKey: _formKey, formFields: [ + Center( + child: MihCircleAvatar( + imageFile: newSelectedLogoPic != null + ? MemoryImage(newSelectedLogoPic!.bytes!) + : mzansiProfileProvider.businessProfilePicture, + width: 150, + editable: true, + fileNameController: logoFileNameController, + userSelectedfile: newSelectedLogoPic, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: (selectedfile) { + setState(() { + newSelectedLogoPic = selectedfile; + }); + }, + ), + ), + const SizedBox(height: 20), MihTextFormField( fillColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == @@ -644,7 +678,7 @@ class _ProfileBusinessAddState extends State { //const SizedBox(height: 15.0), const Center( child: Text( - "My Business User", + "Business User", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 22, @@ -716,7 +750,7 @@ class _ProfileBusinessAddState extends State { return MihValidationServices().isEmpty(value); }, ), - const SizedBox(height: 15.0), + const SizedBox(height: 10.0), MihTextFormField( fillColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == @@ -733,23 +767,41 @@ class _ProfileBusinessAddState extends State { return MihValidationServices().isEmpty(value); }, ), - // MihDropdownField( - // controller: accessController, - // hintText: "Access Type", - // dropdownOptions: const ["Full", "Partial"], - // editable: false, - // enableSearch: true, - // validator: (value) { - // return MihValidationServices().isEmpty(value); - // }, - // requiredText: true, - // ), + const SizedBox(height: 10), + Container( + width: 300, + alignment: Alignment.topLeft, + child: const Text( + "Signature:", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + ), + Center( + child: MihImageDisplay( + imageFile: newSelectedSignaturePic != null + ? MemoryImage(newSelectedSignaturePic!.bytes!) + : mzansiProfileProvider.businessUserSignature, + width: 300, + height: 200, + editable: true, + fileNameController: signtureController, + userSelectedfile: newSelectedSignaturePic, + onChange: (selectedFile) { + setState(() { + newSelectedSignaturePic = selectedFile; + }); + }, + ), + ), const SizedBox(height: 20.0), Center( child: MihButton( onPressed: () { if (_formKey.currentState!.validate()) { - submitForm(); + submitForm(mzansiProfileProvider); } else { MihAlertServices() .formNotFilledCompletely(context); @@ -771,72 +823,15 @@ class _ProfileBusinessAddState extends State { ), ), ), + const SizedBox(height: 30), ], ), ], ), ), ), - ), - ], - ); - } - - @override - void dispose() { - nameController.dispose(); - typeController.dispose(); - regController.dispose(); - logonameController.dispose(); - fnameController.dispose(); - lnameController.dispose(); - titleController.dispose(); - signtureController.dispose(); - accessController.dispose(); - contactController.dispose(); - emailController.dispose(); - locationController.dispose(); - practiceNoController.dispose(); - vatNoController.dispose(); - _focusNode.dispose(); - super.dispose(); - } - - @override - void initState() { - super.initState(); - typeController.addListener(typeSelected); - setState(() { - fnameController.text = widget.signedInUser.fname; - lnameController.text = widget.signedInUser.lname; - accessController.text = "Full"; - countryCodeController.text = "+27"; - }); - if (AppEnviroment.getEnv() == "Prod") { - env = "Prod"; - } else { - env = "Dev"; - } - missionVisionController.addListener(() { - setState(() { - _counter.value = missionVisionController.text.characters.length; - }); - }); - } - - @override - Widget build(BuildContext context) { - double screenWidth = MediaQuery.of(context).size.width; - return MIHLayoutBuilder( - actionButton: getActionButton(), - secondaryActionButton: null, - header: getHeader(), - body: getBody(screenWidth), - actionDrawer: null, - secondaryActionDrawer: null, - bottomNavBar: null, - pullDownToRefresh: false, - onPullDown: () async {}, + ); + }, ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart index 96592644..577efd23 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart @@ -1,4 +1,3 @@ -import 'dart:typed_data'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:file_picker/file_picker.dart'; import 'package:file_saver/file_saver.dart'; @@ -21,6 +20,7 @@ import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; import 'package:screenshot/screenshot.dart'; +import 'package:share_plus/share_plus.dart'; import 'package:supertokens_flutter/supertokens.dart'; class MihBusinessQrCode extends StatefulWidget { @@ -320,6 +320,13 @@ class _MihBusinessQrCodeState extends State { ); } + void shareMIHLink(BuildContext context, String message, String link) { + String shareText = "$message: $link"; + SharePlus.instance.share( + ShareParams(text: shareText), + ); + } + @override void dispose() { super.dispose(); @@ -391,7 +398,31 @@ class _MihBusinessQrCodeState extends State { onTap: () { downloadQrCode(); }, - ) + ), + SpeedDialChild( + child: Icon( + Icons.share_rounded, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + label: "Share Business", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onTap: () { + shareMIHLink( + context, + "Check out ${widget.business.Name} on the MIH app", + "$qrCodedata${widget.business.business_id}", + ); + }, + ), ]), ) ], diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart index dd129042..e15563b8 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 @@ -5,17 +5,14 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart'; import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; class MihBusinessUserSearch extends StatefulWidget { - final BusinessArguments arguments; const MihBusinessUserSearch({ super.key, - required this.arguments, }); @override @@ -33,18 +30,6 @@ class _MihBusinessUserSearchState extends State { Future> fetchUsers(String search) async { return MihUserServices().searchUsers(search, context); - // final response = await http - // .get(Uri.parse("${AppEnviroment.baseApiUrl}/users/search/$search")); - // errorCode = response.statusCode.toString(); - // errorBody = response.body; - // if (response.statusCode == 200) { - // Iterable l = jsonDecode(response.body); - // List users = - // List.from(l.map((model) => AppUser.fromJson(model))); - // return users; - // } else { - // throw Exception('failed to load patients'); - // } } void submitUserForm() { @@ -61,7 +46,6 @@ class _MihBusinessUserSearchState extends State { if (userList.isNotEmpty) { return BuildUserList( users: userList, - arguments: widget.arguments, ); } if (hasSearchedBefore && userSearch.isNotEmpty) { 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 4fb5696f..3dc774a9 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_team.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_team.dart @@ -1,16 +1,14 @@ -import 'dart:convert'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/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'; -import 'package:supertokens_flutter/http.dart' as http; class MihMyBusinessTeam extends StatefulWidget { const MihMyBusinessTeam({ @@ -25,6 +23,12 @@ 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"); @@ -49,9 +53,7 @@ class _MihMyBusinessTeamState extends State { Widget displayEmployeeList(List employeeList) { if (employeeList.isNotEmpty) { - return BuildEmployeeList( - employees: employeeList, - ); + return BuildEmployeeList(); } return Center( child: Text( @@ -87,6 +89,7 @@ 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/personal_profile/components/mih_edit_personal_profile_window.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/components/mih_edit_personal_profile_window.dart new file mode 100644 index 00000000..c4b47711 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/components/mih_edit_personal_profile_window.dart @@ -0,0 +1,470 @@ +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:provider/provider.dart'; + +class MihEditPersonalProfileWindow extends StatefulWidget { + const MihEditPersonalProfileWindow({super.key}); + + @override + State createState() => + _MihEditPersonalProfileWindowState(); +} + +class _MihEditPersonalProfileWindowState + extends State { + TextEditingController proPicController = TextEditingController(); + TextEditingController usernameController = TextEditingController(); + TextEditingController fnameController = TextEditingController(); + TextEditingController lnameController = TextEditingController(); + TextEditingController purposeController = TextEditingController(); + bool _controllersInitialized = false; + final ValueNotifier _counter = ValueNotifier(0); + final _formKey = GlobalKey(); + PlatformFile? newSelectedProPic; + String oldProPicName = ""; + String env = ""; + bool businessUser = false; + + void initializeControllers(MzansiProfileProvider mzansiProfileProvider) { + businessUser = mzansiProfileProvider.user!.type == "business"; + oldProPicName = mzansiProfileProvider.user!.pro_pic_path.isNotEmpty + ? mzansiProfileProvider.user!.pro_pic_path.split("/").last + : ""; + env = AppEnviroment.getEnv() == "Prod" ? env = "Prod" : env = "Dev"; + if (!_controllersInitialized && mzansiProfileProvider.user != null) { + usernameController.text = mzansiProfileProvider.user!.username; + fnameController.text = mzansiProfileProvider.user!.fname; + lnameController.text = mzansiProfileProvider.user!.lname; + purposeController.text = mzansiProfileProvider.user!.purpose; + proPicController.text = + mzansiProfileProvider.user!.pro_pic_path.isNotEmpty + ? mzansiProfileProvider.user!.pro_pic_path.split("/").last + : ""; + businessUser = mzansiProfileProvider.user!.type == "business"; + _controllersInitialized = true; + } + } + + Future submitForm(MzansiProfileProvider mzansiProfileProvider) async { + if (mzansiProfileProvider.user!.username != usernameController.text) { + bool isUsernameUnique = await MihUserServices.isUsernameUnique( + usernameController.text, context); + if (isUsernameUnique == false) { + notUniqueAlert(); + return; + } + } + if (oldProPicName != proPicController.text) { + await uploadSelectedFile(mzansiProfileProvider, newSelectedProPic); + } + await updateUserApiCall(mzansiProfileProvider); + } + + Future updateUserApiCall( + MzansiProfileProvider mzansiProfileProvider) async { + KenLogger.success("businessUser: $businessUser"); + int responseCode = await MihUserServices().updateUserV2( + mzansiProfileProvider.user!, + fnameController.text, + lnameController.text, + usernameController.text, + proPicController.text, + purposeController.text, + businessUser, + context, + ); + if (responseCode == 200) { + setState(() { + setProfileVariables(mzansiProfileProvider); + newSelectedProPic = null; + }); + bool stayOnPersonalSide = true; + // if (originalProfileTypeIsBusiness == false && businessUser == true) { + // stayOnPersonalSide = false; + // } + String message = "Your information has been updated successfully!"; + context.pop(); + successPopUp(message, stayOnPersonalSide); + } else { + internetConnectionPopUp(); + } + } + + Future uploadSelectedFile( + MzansiProfileProvider mzansiProfileProvider, PlatformFile? file) async { + var response = await MihFileApi.uploadFile( + mzansiProfileProvider.user!.app_id, + env, + "profile_files", + file, + context, + ); + if (response == 200) { + deleteFileApiCall(mzansiProfileProvider, oldProPicName); + } else { + internetConnectionPopUp(); + } + } + + Future deleteFileApiCall( + MzansiProfileProvider mzansiProfileProvider, String filename) async { + var response = await MihFileApi.deleteFile( + mzansiProfileProvider.user!.app_id, + env, + "profile_files", + filename, + context, + ); + if (response == 200) { + //SQL delete + } else { + internetConnectionPopUp(); + } + } + + void setProfileVariables(MzansiProfileProvider mzansiProfileProvider) { + businessUser = mzansiProfileProvider.user!.type == "business"; + oldProPicName = mzansiProfileProvider.user!.pro_pic_path.isNotEmpty + ? mzansiProfileProvider.user!.pro_pic_path.split("/").last + : ""; + env = AppEnviroment.getEnv() == "Prod" ? env = "Prod" : env = "Dev"; + } + + Color getPurposeLimitColor(int limit) { + if (_counter.value <= limit) { + return MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } else { + return MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } + } + + void successPopUp(String message, bool stayOnPersonalSide) { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.check_circle_outline_rounded, + size: 150, + color: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: "Successfully Updated Profile", + alertBody: Column( + children: [ + Text( + message, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + context.pop(); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Dismiss", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + // return MIHSuccessMessage( + // successType: "Success", + // successMessage: message, + // ); + }, + ); + } + + void internetConnectionPopUp() { + showDialog( + context: context, + builder: (context) { + return const MIHErrorMessage(errorType: "Internet Connection"); + }, + ); + } + + void notUniqueAlert() { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.warning_amber_rounded, + size: 100, + color: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + alertTitle: "Too Slow, That Username is Taken", + alertBody: const Text( + "The username you have entered is already taken by another member of Mzansi. Please choose a different username and try again.", + style: TextStyle( + fontSize: 15, + ), + ), + alertColour: MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + }, + ); + } + + @override + void initState() { + super.initState(); + initializeControllers(context.read()); + } + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return Consumer( + builder: (BuildContext context, + MzansiProfileProvider mzansiProfileProvider, Widget? child) { + return MihPackageWindow( + fullscreen: false, + windowTitle: "Edit Profile", + onWindowTapClose: () { + Navigator.of(context).pop(); + }, + windowBody: Padding( + padding: + MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: screenWidth * 0.05) + : EdgeInsets.symmetric(horizontal: screenWidth * 0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + MihForm( + formKey: _formKey, + formFields: [ + Center( + child: MihCircleAvatar( + imageFile: newSelectedProPic != null + ? MemoryImage(newSelectedProPic!.bytes!) + : mzansiProfileProvider.userProfilePicture, + width: 150, + editable: true, + fileNameController: proPicController, + userSelectedfile: newSelectedProPic, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: (selectedImage) { + setState(() { + newSelectedProPic = selectedImage; + }); + }, + ), + ), + // const SizedBox(height: 25.0), + Visibility( + visible: false, + child: MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: proPicController, + multiLineInput: false, + requiredText: true, + readOnly: true, + hintText: "Selected File Name", + ), + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: usernameController, + multiLineInput: false, + requiredText: true, + hintText: "Username", + validator: (value) { + return MihValidationServices().validateUsername(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: fnameController, + multiLineInput: false, + requiredText: true, + hintText: "First Name", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: lnameController, + multiLineInput: false, + requiredText: true, + hintText: "Last Name", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + height: 250, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + inputColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + controller: purposeController, + multiLineInput: true, + requiredText: true, + hintText: "Your Personal Mission", + validator: (value) { + return MihValidationServices() + .validateLength(purposeController.text, 256); + }, + ), + SizedBox( + height: 15, + child: ValueListenableBuilder( + valueListenable: _counter, + builder: + (BuildContext context, int value, Widget? child) { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "$value", + style: TextStyle( + color: getPurposeLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 5), + Text( + "/256", + style: TextStyle( + color: getPurposeLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + ], + ); + }, + ), + ), + const SizedBox(height: 10.0), + MihToggle( + hintText: "Activate Business Account", + initialPostion: businessUser, + fillColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + secondaryFillColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: (value) { + setState(() { + businessUser = value; + }); + KenLogger.success("Business User: $businessUser"); + }, + ), + const SizedBox(height: 30.0), + Center( + child: MihButton( + onPressed: () { + //Add validation here + if (_formKey.currentState!.validate()) { + submitForm(mzansiProfileProvider); + } else { + MihAlertServices().formNotFilledCompletely(context); + } + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 300, + child: Text( + "Update", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart index 965ad532..c47af691 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart @@ -1,26 +1,15 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; -import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/components/mih_edit_personal_profile_window.dart'; import 'package:provider/provider.dart'; class MihPersonalProfile extends StatefulWidget { @@ -32,32 +21,7 @@ class MihPersonalProfile extends StatefulWidget { class _MihPersonalProfileState extends State { TextEditingController proPicController = TextEditingController(); - TextEditingController usernameController = TextEditingController(); - TextEditingController fnameController = TextEditingController(); - TextEditingController lnameController = TextEditingController(); - TextEditingController purposeController = TextEditingController(); - final ValueNotifier _counter = ValueNotifier(0); PlatformFile? newSelectedProPic; - bool businessUser = false; - bool _controllersInitialized = false; - String env = ""; - String oldProPicName = ""; - final _formKey = GlobalKey(); - - void initializeControllers(MzansiProfileProvider mzansiProfileProvider) { - if (!_controllersInitialized && mzansiProfileProvider.user != null) { - usernameController.text = mzansiProfileProvider.user!.username; - fnameController.text = mzansiProfileProvider.user!.fname; - lnameController.text = mzansiProfileProvider.user!.lname; - purposeController.text = mzansiProfileProvider.user!.purpose; - proPicController.text = - mzansiProfileProvider.user!.pro_pic_path.isNotEmpty - ? mzansiProfileProvider.user!.pro_pic_path.split("/").last - : ""; - businessUser = mzansiProfileProvider.user!.type == "business"; - _controllersInitialized = true; - } - } void editProfileWindow(double width) { showDialog( @@ -73,401 +37,12 @@ class _MihPersonalProfileState extends State { // mzansiProfileProvider.user!.pro_pic_path.isNotEmpty // ? mzansiProfileProvider.user!.pro_pic_path.split("/").last // : ""; - initializeControllers(mzansiProfileProvider); - return MihPackageWindow( - fullscreen: false, - windowTitle: "Edit Profile", - onWindowTapClose: () { - Navigator.of(context).pop(); - }, - windowBody: Padding( - padding: - MzansiInnovationHub.of(context)!.theme.screenType == "desktop" - ? EdgeInsets.symmetric(horizontal: width * 0.05) - : EdgeInsets.symmetric(horizontal: width * 0), - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - MihForm( - formKey: _formKey, - formFields: [ - Center( - child: MihCircleAvatar( - imageFile: newSelectedProPic != null - ? MemoryImage(newSelectedProPic!.bytes!) - : mzansiProfileProvider.userProfilePicture, - width: 150, - editable: true, - fileNameController: proPicController, - userSelectedfile: newSelectedProPic, - frameColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - backgroundColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - onChange: (selectedImage) { - setState(() { - newSelectedProPic = selectedImage; - }); - }, - ), - ), - // const SizedBox(height: 25.0), - Visibility( - visible: false, - child: MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: proPicController, - multiLineInput: false, - requiredText: true, - readOnly: true, - hintText: "Selected File Name", - ), - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: usernameController, - multiLineInput: false, - requiredText: true, - hintText: "Username", - validator: (value) { - return MihValidationServices() - .validateUsername(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: fnameController, - multiLineInput: false, - requiredText: true, - hintText: "First Name", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: lnameController, - multiLineInput: false, - requiredText: true, - hintText: "Last Name", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - height: 250, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - inputColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - controller: purposeController, - multiLineInput: true, - requiredText: true, - hintText: "Your Personal Mission", - validator: (value) { - return MihValidationServices() - .validateLength(purposeController.text, 256); - }, - ), - SizedBox( - height: 15, - child: ValueListenableBuilder( - valueListenable: _counter, - builder: - (BuildContext context, int value, Widget? child) { - return Row( - mainAxisSize: MainAxisSize.max, - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text( - "$value", - style: TextStyle( - color: getPurposeLimitColor(256), - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(width: 5), - Text( - "/256", - style: TextStyle( - color: getPurposeLimitColor(256), - fontWeight: FontWeight.bold, - ), - ), - ], - ); - }, - ), - ), - const SizedBox(height: 10.0), - MihToggle( - hintText: "Activate Business Account", - initialPostion: businessUser, - fillColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - secondaryFillColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - onChange: (value) { - setState(() { - businessUser = value; - }); - }, - ), - const SizedBox(height: 30.0), - Center( - child: MihButton( - onPressed: () { - //Add validation here - if (_formKey.currentState!.validate()) { - submitForm(mzansiProfileProvider); - } else { - MihAlertServices() - .formNotFilledCompletely(context); - } - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - width: 300, - child: Text( - "Update", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ], - ), - ), - ); + return MihEditPersonalProfileWindow(); }, ), ); } - Future submitForm(MzansiProfileProvider mzansiProfileProvider) async { - if (mzansiProfileProvider.user!.username != usernameController.text) { - bool isUsernameUnique = await MihUserServices.isUsernameUnique( - usernameController.text, context); - if (isUsernameUnique == false) { - notUniqueAlert(); - return; - } - } - if (oldProPicName != proPicController.text) { - await uploadSelectedFile(mzansiProfileProvider, newSelectedProPic); - } - await updateUserApiCall(mzansiProfileProvider); - } - - Future uploadSelectedFile( - MzansiProfileProvider mzansiProfileProvider, PlatformFile? file) async { - var response = await MihFileApi.uploadFile( - mzansiProfileProvider.user!.app_id, - env, - "profile_files", - file, - context, - ); - if (response == 200) { - deleteFileApiCall(mzansiProfileProvider, oldProPicName); - } else { - internetConnectionPopUp(); - } - } - - Future deleteFileApiCall( - MzansiProfileProvider mzansiProfileProvider, String filename) async { - var response = await MihFileApi.deleteFile( - mzansiProfileProvider.user!.app_id, - env, - "profile_files", - filename, - context, - ); - if (response == 200) { - //SQL delete - } else { - internetConnectionPopUp(); - } - } - - Future updateUserApiCall( - MzansiProfileProvider mzansiProfileProvider) async { - int responseCode = await MihUserServices().updateUserV2( - mzansiProfileProvider.user!, - fnameController.text, - lnameController.text, - usernameController.text, - proPicController.text, - purposeController.text, - businessUser, - context, - ); - if (responseCode == 200) { - setState(() { - setProfileVariables(mzansiProfileProvider); - newSelectedProPic = null; - }); - bool stayOnPersonalSide = true; - // if (originalProfileTypeIsBusiness == false && businessUser == true) { - // stayOnPersonalSide = false; - // } - String message = "Your information has been updated successfully!"; - context.pop(); - successPopUp(message, stayOnPersonalSide); - } else { - internetConnectionPopUp(); - } - } - - Color getPurposeLimitColor(int limit) { - if (_counter.value <= limit) { - return MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"); - } else { - return MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"); - } - } - - void setProfileVariables(MzansiProfileProvider mzansiProfileProvider) { - businessUser = mzansiProfileProvider.user!.type == "business"; - oldProPicName = mzansiProfileProvider.user!.pro_pic_path.isNotEmpty - ? mzansiProfileProvider.user!.pro_pic_path.split("/").last - : ""; - env = AppEnviroment.getEnv() == "Prod" ? env = "Prod" : env = "Dev"; - } - - void successPopUp(String message, bool stayOnPersonalSide) { - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.check_circle_outline_rounded, - size: 150, - color: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: "Successfully Updated Profile", - alertBody: Column( - children: [ - Text( - message, - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 15, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 25), - Center( - child: MihButton( - onPressed: () { - context.pop(); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - elevation: 10, - width: 300, - child: Text( - "Dismiss", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ) - ], - ), - alertColour: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - // return MIHSuccessMessage( - // successType: "Success", - // successMessage: message, - // ); - }, - ); - } - - void internetConnectionPopUp() { - showDialog( - context: context, - builder: (context) { - return const MIHErrorMessage(errorType: "Internet Connection"); - }, - ); - } - - void notUniqueAlert() { - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.warning_amber_rounded, - size: 100, - color: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - alertTitle: "Too Slow, That Username is Taken", - alertBody: const Text( - "The username you have entered is already taken by another member of Mzansi. Please choose a different username and try again.", - style: TextStyle( - fontSize: 15, - ), - ), - alertColour: MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ); - }, - ); - } - @override Widget build(BuildContext context) { double screenWidth = MediaQuery.of(context).size.width; @@ -492,11 +67,6 @@ class _MihPersonalProfileState extends State { // editProfileWindow(width); // } else { - businessUser = mzansiProfileProvider.user!.type == "business"; - oldProPicName = mzansiProfileProvider.user!.pro_pic_path.isNotEmpty - ? mzansiProfileProvider.user!.pro_pic_path.split("/").last - : ""; - env = AppEnviroment.getEnv() == "Prod" ? env = "Prod" : env = "Dev"; KenLogger.success( mzansiProfileProvider.userProfilePicture.toString()); return MihSingleChildScroll( @@ -559,7 +129,9 @@ class _MihPersonalProfileState extends State { ), FittedBox( child: Text( - businessUser == true ? "Business" : "Personal", + mzansiProfileProvider.user!.type == "business" + ? "Business".toUpperCase() + : "Personal".toUpperCase(), style: TextStyle( fontSize: 15, fontWeight: FontWeight.bold, diff --git a/Frontend/lib/mih_services/mih_business_details_services.dart b/Frontend/lib/mih_services/mih_business_details_services.dart index 6b976cb9..f12e1282 100644 --- a/Frontend/lib/mih_services/mih_business_details_services.dart +++ b/Frontend/lib/mih_services/mih_business_details_services.dart @@ -120,7 +120,7 @@ class MihBusinessDetailsServices { } Future createBusinessDetails( - String appId, + MzansiProfileProvider provider, String busineName, String businessType, String businessRegistrationNo, @@ -141,9 +141,6 @@ class MihBusinessDetailsServices { return const Mihloadingcircle(); }, ); - String logoPath = businessLogoFilename.isNotEmpty - ? "$appId/business_files/$businessLogoFilename" - : ""; var response = await http.post( Uri.parse("${AppEnviroment.baseApiUrl}/business/insert/"), headers: { @@ -154,7 +151,7 @@ class MihBusinessDetailsServices { "type": businessType, "registration_no": businessRegistrationNo, "logo_name": businessLogoFilename, - "logo_path": logoPath, + "logo_path": "", "contact_no": businessPhoneNumber, "bus_email": businessEmail, "gps_location": businessLocation, @@ -165,7 +162,50 @@ class MihBusinessDetailsServices { "mission_vision": businessMissionVision, }), ); - Navigator.of(context).pop(); + context.pop(); + if (response.statusCode == 201) { + int finalStatusCode = await updateBusinessDetailsV2( + jsonDecode(response.body)['business_id'], + busineName, + businessType, + businessRegistrationNo, + businessPracticeNo, + businessVatNo, + businessEmail, + businessPhoneNumber, + businessLocation, + businessLogoFilename, + businessWebsite, + businessRating, + businessMissionVision, + provider, + context, + ); + if (finalStatusCode == 200) { + String logoPath = businessLogoFilename.isNotEmpty + ? "${jsonDecode(response.body)['business_id']}/business_files/$businessLogoFilename" + : ""; + provider.setBusiness( + newBusiness: Business( + jsonDecode(response.body)['business_id'], + busineName, + businessType, + businessRegistrationNo, + businessLogoFilename, + logoPath, + businessPhoneNumber, + businessEmail, + provider.user!.app_id, + businessLocation, + businessPracticeNo, + businessVatNo, + businessWebsite, + businessRating, + businessMissionVision, + ), + ); + } + } return response; } @@ -227,7 +267,7 @@ class MihBusinessDetailsServices { filePath, business_phone_number, business_email, - provider.business!.app_id, + business_id, business_location, business_practice_no, business_vat_no, diff --git a/Frontend/lib/mih_services/mih_business_employee_services.dart b/Frontend/lib/mih_services/mih_business_employee_services.dart new file mode 100644 index 00000000..4518437b --- /dev/null +++ b/Frontend/lib/mih_services/mih_business_employee_services.dart @@ -0,0 +1,142 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:supertokens_flutter/http.dart' as http; + +class MihBusinessEmployeeServices { + Future fetchEmployees( + MzansiProfileProvider mzansiProfileProvider, BuildContext context) async { + final response = await http.get(Uri.parse( + "${AppEnviroment.baseApiUrl}/business-user/employees/${mzansiProfileProvider.businessUser!.business_id}")); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List employeeList = List.from( + l.map((model) => BusinessEmployee.fromJson(model))); + mzansiProfileProvider.setEmployeeList(employeeList: employeeList); + } else { + throw Exception('failed to load employees'); + } + return response.statusCode; + } + + Future addEmployee( + MzansiProfileProvider provider, + AppUser newEmployee, + String access, + BuildContext context, + ) async { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle(); + }, + ); + var response = await http.post( + Uri.parse("${AppEnviroment.baseApiUrl}/business-user/insert/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "business_id": provider.business!.business_id, + "app_id": newEmployee.app_id, + "signature": "", + "sig_path": "", + "title": "", + "access": access, + }), + ); + if (response.statusCode == 201) { + provider.addEmployee( + newEmployee: BusinessEmployee( + provider.business!.business_id, + newEmployee.app_id, + "", + access, + newEmployee.fname, + newEmployee.lname, + newEmployee.email, + newEmployee.username, + ), + ); + provider.setBusinessIndex(2); + } + context.pop(); + return response.statusCode; + } + + Future updateEmployeeDetails( + MzansiProfileProvider provider, + BusinessEmployee employee, + String newTitle, + String newAccess, + BuildContext context) async { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle(); + }, + ); + var response = await http.put( + Uri.parse("${AppEnviroment.baseApiUrl}/business-user/employees/update/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "business_id": employee.business_id, + "app_id": employee.app_id, + "title": newTitle, + "access": newAccess, + }), + ); + if (response.statusCode == 200) { + provider.updateEmplyeeDetails( + updatedEmployee: BusinessEmployee( + employee.business_id, + employee.app_id, + newTitle, + newAccess, + employee.fname, + employee.lname, + employee.email, + employee.username, + ), + ); + } + context.pop(); + return response.statusCode; + } + + Future deleteEmployee( + MzansiProfileProvider provider, + BusinessEmployee employee, + BuildContext context, + ) async { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle(); + }, + ); + var response = await http.delete( + Uri.parse("${AppEnviroment.baseApiUrl}/business-user/employees/delete/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "business_id": employee.business_id, + "app_id": employee.app_id, + }), + ); + if (response.statusCode == 200) { + provider.deleteEmplyee(deletedEmployee: employee); + } + context.pop(); + return response.statusCode; + } +} diff --git a/Frontend/lib/mih_services/mih_file_services.dart b/Frontend/lib/mih_services/mih_file_services.dart index 88746f66..e3eec301 100644 --- a/Frontend/lib/mih_services/mih_file_services.dart +++ b/Frontend/lib/mih_services/mih_file_services.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:file_picker/file_picker.dart'; import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_success_message.dart'; @@ -44,8 +45,9 @@ class MihFileApi { fileUrl = decodedData['minioURL']; } else { // internetConnectionPopUp(context); - print("Error: ${response.statusCode}"); - print("Error: ${response.body}"); + KenLogger.error("Get File Error: $url"); + KenLogger.error("Get File Error: ${response.statusCode}"); + KenLogger.error("Get File Error: ${response.body}"); } } catch (e) { // internetConnectionPopUp(context); diff --git a/Frontend/lib/mih_services/mih_my_business_user_services.dart b/Frontend/lib/mih_services/mih_my_business_user_services.dart index 5b0f5349..bb927b5f 100644 --- a/Frontend/lib/mih_services/mih_my_business_user_services.dart +++ b/Frontend/lib/mih_services/mih_my_business_user_services.dart @@ -1,6 +1,5 @@ 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/business_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:flutter/material.dart'; @@ -24,7 +23,7 @@ class MihMyBusinessUserServices { }, ); if (response.statusCode == 200) { - KenLogger.success(response.body); + // KenLogger.success(response.body); BusinessUser? businessUser = BusinessUser.fromJson(jsonDecode(response.body)); context @@ -42,6 +41,7 @@ class MihMyBusinessUserServices { String signatureFilename, String title, String access, + MzansiProfileProvider provider, BuildContext context, ) async { showDialog( @@ -50,6 +50,7 @@ class MihMyBusinessUserServices { return const Mihloadingcircle(); }, ); + String sigPath = "$business_id/business_files/$signatureFilename"; var response = await http.post( Uri.parse("${AppEnviroment.baseApiUrl}/business-user/insert/"), headers: { @@ -59,13 +60,17 @@ class MihMyBusinessUserServices { "business_id": business_id, "app_id": app_id, "signature": signatureFilename, - "sig_path": "$business_id/business_files/$signatureFilename", + "sig_path": sigPath, "title": title, "access": access, }), ); context.pop(); if (response.statusCode == 201) { + provider.setBusinessUser( + newBusinessUser: BusinessUser( + 0, business_id, app_id, signatureFilename, sigPath, title, access), + ); return 201; } else { internetConnectionPopUp(context); diff --git a/Frontend/lib/mih_services/mih_user_services.dart b/Frontend/lib/mih_services/mih_user_services.dart index ff74e988..3467f7f0 100644 --- a/Frontend/lib/mih_services/mih_user_services.dart +++ b/Frontend/lib/mih_services/mih_user_services.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; @@ -132,11 +133,13 @@ class MihUserServices { var fileName = profilePicture.replaceAll(RegExp(r' '), '-'); var filePath = "${signedInUser.app_id}/profile_files/$fileName"; String profileType; + KenLogger.success("is Busines User: $isBusinessUser"); if (isBusinessUser) { profileType = "business"; } else { profileType = "personal"; } + KenLogger.success("Profile Type: $profileType"); var response = await http.put( Uri.parse("${AppEnviroment.baseApiUrl}/user/update/v2/"), headers: {