From 6fbe720fa3b419ced187e6506b17236206e3f664 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 3 Jul 2025 10:44:39 +0200 Subject: [PATCH 01/68] Add Mzansi Directory Icon --- .../assets/fonts/Mih_Icons.ttf | Bin 41392 -> 44128 bytes .../assets/fonts/style.css | 82 +++++++++--------- .../mih_package_components/mih_icons.dart | 44 ++++++---- 3 files changed, 68 insertions(+), 58 deletions(-) diff --git a/Frontend/lib/mih_components/mih_package_components/assets/fonts/Mih_Icons.ttf b/Frontend/lib/mih_components/mih_package_components/assets/fonts/Mih_Icons.ttf index 29479c3b0ec6b31e5cc6b7e29b6fe79259087f64..71c04e155aa0042fcb72d33ab638b33a0cfd01d5 100644 GIT binary patch delta 1418 zcmY*ZT}&KR6u#%)JOAt~J2U&kvb*fg)?ES!l%L&NC`+5t8XE;=Yiew;gqCg$6cU;g zZQ`O2MgvX6NojmgXi^)j^(Pr0eCR_P<4YfEjh2|EF-Cn5Tdfaj^a1e9BK}Nf?m6c> zKleN5X6}cd&~Lt?Wdei{jm!{6TKflE+Wdw%g~%2Bj*N^CPm(vU*n~g~?W4zsrzTNW zqdkLCK0fx`XoT*65A9b7S&o&C4Igbf5dEBxcP^kmS3*EqVLzgM2kmX8@sraBil~uG z-clT!7}-61E>AQ(hS}Gt^)6;A8MIEWk2+3}3=sT1T7ccABGIw3nWuuhGl&I=#mNtep)ohh228w%>4O z2D+U4R4lhZGjw+33b3Wnw4Fg9-vfnz)h;h4pKEJx3xyMaZ_t!<$l95-8A#h=9MBQ8 z#73xt|0v;*CD~%y58+B024GTJ3W}jFc%TPMX0qjGXoNs}TP~k%hJshdOVUBIGucgK z(?(L+d@~?~#PYc<7L|&UXlD!1naiLTH;cjc%665a*ac)WUN;`^kcC_}`CB2+-_z-p z#Mj$W4Ans%+r(gxT1LdsywsTvw(o-fE#Rb1=iEuVk(Srqr6Lt5$O_|%43f&2DuJX3 z03b3C;FMvAC~D%)g*Q3{Dgp-(q{a^po~HW}F(qJ$qG>?DtO!F>fHA0&4KNgqQY-_i zYJwcAgQrlZH23V{($jtPzCbB|w494j#%M6Vt)8}W;Otk%I7=Nmlww1AQcLQlZ2L2h z$2DC<7OK_~@uhrwtGq(KbPIqis#Sj7Czq(iWUlxvHKr&!=Uh;jOc};8gGo%_ni}p) z>QPCTEg2{~C`pnWNK>8K{y#E*KkIAm(nudI`#_+AY(xN*+L%i5fI+RTRRJ1(QJ+Nt zn`+WxVf0Wu5P{)7IK#c4uK%g{a5fM}TBf1I6G{`{sy1TRyuiFdI1r!Z3wknO;RH^c zeg8?+*M0%$#0CVQTr6{sH{`h>U>|~Ku^r4%6HjFQwruEeEnKbo0#=O?Obd)fg@kT+ zt=hW9aP*7~;u#5=Rj&#la9vW8vdnQlTr)I(R59vI-O{2}eyLWE?G7n1ql%kim8|HP z6SVxAek+iAwK_Fhot&*st&h6%^+j-&_eI>|!rL-f-v8=;1`P>kelFL{%Aef!9s{vAcVa`6P+mBrie7m14f)&Kwi delta 428 zcmaEGgK5KIrg{cO1_lOhh6V;^1_S?KeItG$Ha(!o9w1Ig&P^;354$vtfq_v5$PY Date: Thu, 3 Jul 2025 10:45:44 +0200 Subject: [PATCH 02/68] add mzansi directory route path --- Frontend/lib/mih_config/mih_routeGenerator.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Frontend/lib/mih_config/mih_routeGenerator.dart b/Frontend/lib/mih_config/mih_routeGenerator.dart index cc20eb9f..17fd4536 100644 --- a/Frontend/lib/mih_config/mih_routeGenerator.dart +++ b/Frontend/lib/mih_config/mih_routeGenerator.dart @@ -15,6 +15,7 @@ import 'package:mzansi_innovation_hub/mih_packages/calculator/mih_calculator.dar import 'package:mzansi_innovation_hub/mih_packages/calendar/mzansi_calendar.dart'; import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/mih_authentication.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/mzansi_ai.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/mzansi_directory.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/profile_business_add.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart'; @@ -50,6 +51,7 @@ class AppRoutes { static const String patientProfileSetup = '/patient-profile/set-up'; static const String patientProfileEdit = '/patient-profile/edit'; static const String mzansiWallet = '/mzansi-wallet'; + static const String mzansiDirectory = '/mzansi-directory'; static const String mihAccess = '/mih-access'; static const String calendar = '/calendar'; static const String appointments = @@ -115,6 +117,14 @@ class RouteGenerator { ); // } // break; // Use break and fall through to _errorRoute if argument type is wrong + case AppRoutes.mzansiDirectory: + // if (args is AuthArguments) { + return MaterialPageRoute( + settings: settings, + builder: (_) => MzansiDirectory(), + ); + // } + // break; case AppRoutes.notifications: if (args is NotificationArguments) { return MaterialPageRoute( From 5568346baf8569319fa022d59018289e1bb8acb3 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 3 Jul 2025 10:46:29 +0200 Subject: [PATCH 03/68] create mzansi director package --- .../mzansi_directory/mzansi_directory.dart | 84 +++++++++++++++++++ .../package_tiles/mzansi_directory_tile.dart | 38 +++++++++ 2 files changed, 122 insertions(+) create mode 100644 Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart create mode 100644 Frontend/lib/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart diff --git a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart new file mode 100644 index 00000000..a356853b --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.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'; + +class MzansiDirectory extends StatefulWidget { + const MzansiDirectory({super.key}); + + @override + State createState() => _MzansiDirectoryState(); +} + +class _MzansiDirectoryState extends State { + int _selcetedIndex = 0; + + @override + Widget build(BuildContext context) { + return MihPackage( + appActionButton: getAction(), + appTools: getTools(), + appBody: getToolBody(), + appToolTitles: getToolTitle(), + selectedbodyIndex: _selcetedIndex, + onIndexChange: (newValue) { + setState(() { + _selcetedIndex = newValue; + }); + print("Index: $_selcetedIndex"); + }, + ); + } + + List getToolBody() { + List toolBodies = [ + Placeholder(), + Placeholder(), + Placeholder(), + ]; + return toolBodies; + } + + MihPackageAction getAction() { + return MihPackageAction( + icon: const Icon(Icons.arrow_back), + iconSize: 35, + onTap: () { + Navigator.of(context).pop(); + FocusScope.of(context).unfocus(); + }, + ); + } + + MihPackageTools getTools() { + Map temp = {}; + temp[const Icon(Icons.person)] = () { + setState(() { + _selcetedIndex = 0; + }); + }; + temp[const Icon(Icons.business_center)] = () { + setState(() { + _selcetedIndex = 1; + }); + }; + temp[const Icon(Icons.search)] = () { + setState(() { + _selcetedIndex = 2; + }); + }; + return MihPackageTools( + tools: temp, + selcetedIndex: _selcetedIndex, + ); + } + + List getToolTitle() { + List toolTitles = [ + "Contacts", + "Favourite Businesses", + "Search Mzansi", + ]; + return toolTitles; + } +} diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart new file mode 100644 index 00000000..f37eae32 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart'; + +class MzansiDirectoryTile extends StatefulWidget { + final double packageSize; + const MzansiDirectoryTile({ + super.key, + required this.packageSize, + }); + + @override + State createState() => _MzansiDirectoryTileState(); +} + +class _MzansiDirectoryTileState extends State { + @override + Widget build(BuildContext context) { + return MihPackageTile( + onTap: () { + Navigator.of(context).pushNamed( + '/mzansi-directory', + // arguments: WalletArguments(widget.signedInUser, 0), + ); + }, + appName: "Mzansi Directory", + appIcon: Icon( + MihIcons.mzansiDirectory, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + // size: widget.packageSize, + ), + iconSize: widget.packageSize, + primaryColor: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + secondaryColor: MzanziInnovationHub.of(context)!.theme.primaryColor(), + ); + } +} From 08bc277fec4d6011c178dbc416ac481b6a7d5fd9 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 3 Jul 2025 10:46:57 +0200 Subject: [PATCH 04/68] add mzansi directory to home --- .../mih_home/package_tools/mih_personal_home.dart | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart index dfd07ba9..00ba3e31 100644 --- a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart +++ b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart @@ -1,4 +1,3 @@ -import 'package:flutter/services.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; @@ -14,6 +13,7 @@ import 'package:mzansi_innovation_hub/mih_packages/access_review/package_tile/mi import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tiles/mih_calculator_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/calendar/package_tiles/mzansi_calendar_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tiles/mzansi_ai_tile.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_profile_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_setup_profile_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/package_tiles/mih_wallet_tile.dart'; @@ -133,6 +133,12 @@ class _MihPersonalHomeState extends State packageSize: packageSize, ) }); + //=============== Mzansi AI =============== + temp.add({ + "Mzansi Directory": MzansiDirectoryTile( + packageSize: packageSize, + ) + }); //=============== Calculator =============== temp.add({ "Calculator": MihCalculatorTile( From 32882bd4e6f7da94734355cdb176144420ab0794 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 3 Jul 2025 11:52:14 +0200 Subject: [PATCH 05/68] add mihsearch to tools --- .../mzansi_directory/mzansi_directory.dart | 10 ++-- .../package_tools/mih_contacts.dart | 50 ++++++++++++++++++ .../mih_favourite_businesses.dart | 51 +++++++++++++++++++ .../package_tools/mih_search_mzansi.dart | 50 ++++++++++++++++++ 4 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_contacts.dart create mode 100644 Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart create mode 100644 Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart diff --git a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart index a356853b..3bdfc329 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart @@ -2,6 +2,9 @@ import 'package:flutter/material.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_packages/mzansi_directory/package_tools/mih_contacts.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart'; class MzansiDirectory extends StatefulWidget { const MzansiDirectory({super.key}); @@ -25,16 +28,15 @@ class _MzansiDirectoryState extends State { setState(() { _selcetedIndex = newValue; }); - print("Index: $_selcetedIndex"); }, ); } List getToolBody() { List toolBodies = [ - Placeholder(), - Placeholder(), - Placeholder(), + MihContacts(), + MihFavouriteBusinesses(), + MihSearchMzansi(), ]; return toolBodies; } diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_contacts.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_contacts.dart new file mode 100644 index 00000000..22d57c0e --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_contacts.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; + +class MihContacts extends StatefulWidget { + const MihContacts({super.key}); + + @override + State createState() => _MihContactsState(); +} + +class _MihContactsState extends State { + final TextEditingController contactSearchController = TextEditingController(); + final FocusNode searchFocusNode = FocusNode(); + + @override + Widget build(BuildContext context) { + final Size size = MediaQuery.sizeOf(context); + final double width = size.width; + return MihPackageToolBody( + borderOn: false, + bodyItem: getBody(width), + ); + } + + Widget getBody(double width) { + return MihSingleChildScroll( + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: MihSearchBar( + controller: contactSearchController, + hintText: "Search Contacts", + prefixIcon: Icons.search, + fillColor: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + hintColor: MzanziInnovationHub.of(context)!.theme.primaryColor(), + onPrefixIconTap: () {}, + searchFocusNode: searchFocusNode, + ), + ), + const SizedBox(height: 10), + ], + ), + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart new file mode 100644 index 00000000..ca16cfc3 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; + +class MihFavouriteBusinesses extends StatefulWidget { + const MihFavouriteBusinesses({super.key}); + + @override + State createState() => _MihFavouriteBusinessesState(); +} + +class _MihFavouriteBusinessesState extends State { + final TextEditingController businessSearchController = + TextEditingController(); + final FocusNode searchFocusNode = FocusNode(); + + @override + Widget build(BuildContext context) { + final Size size = MediaQuery.sizeOf(context); + final double width = size.width; + return MihPackageToolBody( + borderOn: false, + bodyItem: getBody(width), + ); + } + + Widget getBody(double width) { + return MihSingleChildScroll( + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: MihSearchBar( + controller: businessSearchController, + hintText: "Search Businesses", + prefixIcon: Icons.search, + fillColor: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + hintColor: MzanziInnovationHub.of(context)!.theme.primaryColor(), + onPrefixIconTap: () {}, + searchFocusNode: searchFocusNode, + ), + ), + const SizedBox(height: 10), + ], + ), + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart new file mode 100644 index 00000000..24d18acc --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; + +class MihSearchMzansi extends StatefulWidget { + const MihSearchMzansi({super.key}); + + @override + State createState() => _MihSearchMzansiState(); +} + +class _MihSearchMzansiState extends State { + final TextEditingController mzansiSearchController = TextEditingController(); + final FocusNode searchFocusNode = FocusNode(); + + @override + Widget build(BuildContext context) { + final Size size = MediaQuery.sizeOf(context); + final double width = size.width; + return MihPackageToolBody( + borderOn: false, + bodyItem: getBody(width), + ); + } + + Widget getBody(double width) { + return MihSingleChildScroll( + child: Column( + children: [ + Padding( + padding: EdgeInsets.symmetric(horizontal: width / 20), + child: MihSearchBar( + controller: mzansiSearchController, + hintText: "Search Mzansi", + prefixIcon: Icons.search, + fillColor: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + hintColor: MzanziInnovationHub.of(context)!.theme.primaryColor(), + onPrefixIconTap: () {}, + searchFocusNode: searchFocusNode, + ), + ), + const SizedBox(height: 10), + ], + ), + ); + } +} From e7cecfa15c3636a9557435d4eef491f7b67e5ef5 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 3 Jul 2025 11:52:27 +0200 Subject: [PATCH 06/68] comment out unused code --- .../components/mih_business_card.dart | 120 +++++++++--------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart index 32316654..6cba0fe2 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart @@ -171,66 +171,66 @@ class _MihBusinessCardState extends State { } } - Future _launchWebsite(String urlString) async { - final Uri url = Uri.parse(urlString); - try { - if (await canLaunchUrl(url)) { - await launchUrl(url); - } else { - print('Could not launch $urlString'); - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.warning_rounded, - size: 100, - ), - alertTitle: "Error Opening Website", - alertBody: Column( - children: [ - Text( - "Unable to lauch ${widget.businessName}", - style: TextStyle( - color: - MzanziInnovationHub.of(context)!.theme.errorColor(), - fontSize: 15, - ), - ), - ], - ), - alertColour: - MzanziInnovationHub.of(context)!.theme.errorColor(), - ); - }); - } - } catch (e) { - showDialog( - context: context, - builder: (context) { - return MihPackageAlert( - alertIcon: Icon( - Icons.warning_rounded, - size: 100, - ), - alertTitle: "Error Opening Website", - alertBody: Column( - children: [ - Text( - "Unable to lauch ${widget.businessName}", - style: TextStyle( - color: - MzanziInnovationHub.of(context)!.theme.errorColor(), - fontSize: 15, - ), - ), - ], - ), - alertColour: MzanziInnovationHub.of(context)!.theme.errorColor(), - ); - }); - } - } + // Future _launchWebsite(String urlString) async { + // final Uri url = Uri.parse(urlString); + // try { + // if (await canLaunchUrl(url)) { + // await launchUrl(url); + // } else { + // print('Could not launch $urlString'); + // showDialog( + // context: context, + // builder: (context) { + // return MihPackageAlert( + // alertIcon: Icon( + // Icons.warning_rounded, + // size: 100, + // ), + // alertTitle: "Error Opening Website", + // alertBody: Column( + // children: [ + // Text( + // "Unable to lauch ${widget.businessName}", + // style: TextStyle( + // color: + // MzanziInnovationHub.of(context)!.theme.errorColor(), + // fontSize: 15, + // ), + // ), + // ], + // ), + // alertColour: + // MzanziInnovationHub.of(context)!.theme.errorColor(), + // ); + // }); + // } + // } catch (e) { + // showDialog( + // context: context, + // builder: (context) { + // return MihPackageAlert( + // alertIcon: Icon( + // Icons.warning_rounded, + // size: 100, + // ), + // alertTitle: "Error Opening Website", + // alertBody: Column( + // children: [ + // Text( + // "Unable to lauch ${widget.businessName}", + // style: TextStyle( + // color: + // MzanziInnovationHub.of(context)!.theme.errorColor(), + // fontSize: 15, + // ), + // ), + // ], + // ), + // alertColour: MzanziInnovationHub.of(context)!.theme.errorColor(), + // ); + // }); + // } + // } Widget _buildContactInfo( String label, From 32d408bdf671dc47eed3e3bad4734629dcd05007 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 3 Jul 2025 14:34:46 +0200 Subject: [PATCH 07/68] update api to cater for new fields --- backend/routers/users.py | 43 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/backend/routers/users.py b/backend/routers/users.py index bb3c1311..7c51120e 100644 --- a/backend/routers/users.py +++ b/backend/routers/users.py @@ -22,6 +22,15 @@ class userInsertRequest(BaseModel): email: str app_id: str +class userUpdateRequestV2(BaseModel): + idusers: int + username: str + fnam: str + lname: str + type: str + pro_pic_path: str + purpose: str + class userUpdateRequest(BaseModel): idusers: int username: str @@ -76,6 +85,7 @@ async def read_all_users(search: str, session: SessionContainer = Depends(verify "app_id": item[5], "username": item[6], "pro_pic_path": item[7], + "purpose": item[8], } for item in cursor.fetchall() ] @@ -113,6 +123,7 @@ async def read_users_by_app_id(app_id: str, session: SessionContainer = Depends( "app_id": item[5], "username": item[6], "pro_pic_path": item[7], + "purpose": item[8], } for item in cursor.fetchall() ] @@ -126,10 +137,10 @@ async def insert_User_details(itemRequest : userInsertRequest, session: SessionC db = database.dbConnection.dbAppDataConnect() cursor = db.cursor() query = "insert into users " - query += "(email, fname, lname, type, app_id, username, pro_pic_path) " - query += "values (%s, %s, %s, %s, %s, %s, %s)" + query += "(email, fname, lname, type, app_id, username, pro_pic_path, purpose) " + query += "values (%s, %s, %s, %s, %s, %s, %s, %s)" userData = (itemRequest.email,"","","personal", - itemRequest.app_id, "", "") + itemRequest.app_id, "", "","") try: cursor.execute(query, userData) except Exception as error: @@ -140,6 +151,32 @@ async def insert_User_details(itemRequest : userInsertRequest, session: SessionC db.close() return {"message": "Successfully Created Record"} +# Update User on table +@router.put("/user/update/v2/", tags=["MIH Users"]) +async def Update_User_details(itemRequest : userUpdateRequestV2, session: SessionContainer = Depends(verify_session())): + db = database.dbConnection.dbAppDataConnect() + cursor = db.cursor() + query = "update users " + query += "set username=%s, fname=%s, lname=%s, type=%s, pro_pic_path=%s, purpose=%s " + query += "where idusers=%s" + userData = (itemRequest.username, + itemRequest.fnam, + itemRequest.lname, + itemRequest.type, + itemRequest.pro_pic_path, + itemRequest.purpose, + itemRequest.idusers, + ) + try: + cursor.execute(query, userData) + except Exception as error: + raise HTTPException(status_code=404, detail=error) + #return {"query": query, "message": error} + db.commit() + cursor.close() + db.close() + return {"message": "Successfully Updated Record"} + # Update User on table @router.put("/user/update/", tags=["MIH Users"]) async def Update_User_details(itemRequest : userUpdateRequest, session: SessionContainer = Depends(verify_session())): From 7b79ad619a3ea2885f7defc6a13a0894f0f2640e Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 3 Jul 2025 14:35:07 +0200 Subject: [PATCH 08/68] update appUser object to cater for new fields --- Frontend/lib/mih_components/mih_objects/app_user.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Frontend/lib/mih_components/mih_objects/app_user.dart b/Frontend/lib/mih_components/mih_objects/app_user.dart index ca98edbf..94a00a7d 100644 --- a/Frontend/lib/mih_components/mih_objects/app_user.dart +++ b/Frontend/lib/mih_components/mih_objects/app_user.dart @@ -8,6 +8,7 @@ class AppUser { final String app_id; final String username; final String pro_pic_path; + final String purpose; const AppUser( this.idUser, @@ -18,6 +19,7 @@ class AppUser { this.app_id, this.username, this.pro_pic_path, + this.purpose, ); factory AppUser.fromJson(dynamic json) { @@ -30,6 +32,7 @@ class AppUser { json['app_id'], json['username'], json['pro_pic_path'], + json['purpose'], ); } } From 25ee295394483bb70454137f5fa3f606248e38d6 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 3 Jul 2025 14:35:24 +0200 Subject: [PATCH 09/68] update service to matchg apis --- .../lib/mih_services/mih_user_services.dart | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/Frontend/lib/mih_services/mih_user_services.dart b/Frontend/lib/mih_services/mih_user_services.dart index 1432da4d..4c8f9551 100644 --- a/Frontend/lib/mih_services/mih_user_services.dart +++ b/Frontend/lib/mih_services/mih_user_services.dart @@ -83,6 +83,46 @@ class MihUserServices { } } + Future updateUserV2( + AppUser signedInUser, + String firstName, + String lastName, + String username, + String profilePicture, + String purpose, + bool isBusinessUser, + BuildContext context, + ) async { + var fileName = profilePicture.replaceAll(RegExp(r' '), '-'); + var filePath = "${signedInUser.app_id}/profile_files/$fileName"; + String profileType; + if (isBusinessUser) { + profileType = "business"; + } else { + profileType = "personal"; + } + var response = await http.put( + Uri.parse("${AppEnviroment.baseApiUrl}/user/update/v2/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "idusers": signedInUser.idUser, + "username": username, + "fnam": firstName, + "lname": lastName, + "type": profileType, + "pro_pic_path": filePath, + "purpose": purpose, + }), + ); + if (response.statusCode == 200) { + return response.statusCode; + } else { + return response.statusCode; + } + } + Future updateUser( AppUser signedInUser, String firstName, From af44aa314966488065a5995f9b056817b4d7953c Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 3 Jul 2025 14:54:30 +0200 Subject: [PATCH 10/68] multiline text overflow fix --- .../Example/package_tools/package_tool_one.dart | 4 ++++ .../mih_package_components/mih_text_form_field.dart | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart index 351c9e83..4290ae18 100644 --- a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart +++ b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart @@ -361,6 +361,10 @@ class _PackageToolOneState extends State { multiLineInput: true, requiredText: false, hintText: "Enter Multi Line Text", + validator: (value) { + return MihValidationServices() + .validateLength(_textFieldFourController.text, 50); + }, ), const SizedBox(height: 20), Align( diff --git a/Frontend/lib/mih_components/mih_package_components/mih_text_form_field.dart b/Frontend/lib/mih_components/mih_package_components/mih_text_form_field.dart index d276d33e..986b1d21 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_text_form_field.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_text_form_field.dart @@ -87,10 +87,12 @@ class _MihTextFormFieldState extends State { @override Widget build(BuildContext context) { + final isMultiline = widget.multiLineInput == true; return Center( child: SizedBox( width: widget.width, - height: widget.height, + // height: widget.height, + height: isMultiline ? null : widget.height, child: Theme( data: Theme.of(context).copyWith( textSelectionTheme: TextSelectionThemeData( From bc5850272c6c12c8550287f1535d30e1eb5a086a Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 3 Jul 2025 14:56:43 +0200 Subject: [PATCH 11/68] add purpose display and edit field --- .../package_tools/mih_personal_profile.dart | 104 +++++++++++++++--- 1 file changed, 87 insertions(+), 17 deletions(-) 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 bbff0a47..b72400e0 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 @@ -37,6 +37,8 @@ class _MihPersonalProfileState extends State { final usernameController = TextEditingController(); final fnameController = TextEditingController(); final lnameController = TextEditingController(); + final purposeController = TextEditingController(); + final ValueNotifier _counter = ValueNotifier(0); PlatformFile? proPic; late ImageProvider? propicPreview; late bool businessUser; @@ -112,12 +114,13 @@ class _MihPersonalProfileState extends State { } Future updateUserApiCall() async { - int responseCode = await MihUserServices().updateUser( + int responseCode = await MihUserServices().updateUserV2( widget.arguments.signedInUser, fnameController.text, lnameController.text, usernameController.text, proPicController.text, + purposeController.text, businessUser, context, ); @@ -184,6 +187,14 @@ class _MihPersonalProfileState extends State { ); } + Color getPurposeLimitColor(int limit) { + if (_counter.value <= limit) { + return MzanziInnovationHub.of(context)!.theme.secondaryColor(); + } else { + return MzanziInnovationHub.of(context)!.theme.errorColor(); + } + } + void editProfileWindow(double width) { showDialog( context: context, @@ -282,6 +293,52 @@ class _MihPersonalProfileState extends State { }, ), const SizedBox(height: 10.0), + MihTextFormField( + height: 250, + fillColor: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + inputColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + controller: purposeController, + multiLineInput: true, + requiredText: true, + hintText: "Your Purpose", + validator: (value) { + return MihValidationServices() + .validateLength(purposeController.text, 256); + }, + ), + SizedBox( + height: 15, + child: ValueListenableBuilder( + 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, + ), + ), + ], + ); + }, + valueListenable: _counter, + ), + ), + const SizedBox(height: 10.0), MihToggle( hintText: "Activate Business Account", initialPostion: businessUser, @@ -341,6 +398,7 @@ class _MihPersonalProfileState extends State { @override void initState() { + super.initState(); var proPicName = ""; if (widget.arguments.signedInUser.pro_pic_path.isNotEmpty) { proPicName = widget.arguments.signedInUser.pro_pic_path.split("/").last; @@ -350,6 +408,11 @@ class _MihPersonalProfileState extends State { } else { env = "Dev"; } + purposeController.addListener(() { + setState(() { + _counter.value = purposeController.text.characters.length; + }); + }); setState(() { propicPreview = widget.arguments.propicFile; oldProPicName = proPicName; @@ -357,9 +420,9 @@ class _MihPersonalProfileState extends State { fnameController.text = widget.arguments.signedInUser.fname; lnameController.text = widget.arguments.signedInUser.lname; usernameController.text = widget.arguments.signedInUser.username; + purposeController.text = widget.arguments.signedInUser.purpose; businessUser = isBusinessUser(); }); - super.initState(); } @override @@ -438,20 +501,25 @@ class _MihPersonalProfileState extends State { ), ), ), - // const SizedBox(height: 10.0), - // Center( - // child: Text( - // "*DEMO TEXT* This would be the bio of the user telling us a bit about themself and let. This would be the bio of the user telling us a bit about themself and let. This would be the bio of the user telling us a bit about themself", - // textAlign: TextAlign.center, - // style: TextStyle( - // fontSize: 15, - // fontWeight: FontWeight.bold, - // color: MzanziInnovationHub.of(context)! - // .theme - // .secondaryColor(), - // ), - // ), - // ), + const SizedBox(height: 10.0), + Center( + child: SizedBox( + width: 700, + child: Text( + widget.arguments.signedInUser.purpose.isNotEmpty + ? widget.arguments.signedInUser.purpose + : "No purpose added yet", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + ), + ), + ), + ), const SizedBox(height: 30.0), Center( child: MihButton( @@ -463,7 +531,9 @@ class _MihPersonalProfileState extends State { MzanziInnovationHub.of(context)!.theme.successColor(), width: 300, child: Text( - "Edit Profile", + widget.arguments.signedInUser.username.isEmpty + ? "Set Up Profile" + : "Edit Profile", style: TextStyle( color: MzanziInnovationHub.of(context)! .theme From df026dcfe75fdf634f43ab0bf39e4625bfc2d9db Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Fri, 4 Jul 2025 10:21:03 +0200 Subject: [PATCH 12/68] toggle fix from inside mih windows --- .../mih_package_components/mih_toggle.dart | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/Frontend/lib/mih_components/mih_package_components/mih_toggle.dart b/Frontend/lib/mih_components/mih_package_components/mih_toggle.dart index 2b113a90..0dd660f6 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_toggle.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_toggle.dart @@ -25,12 +25,20 @@ class MihToggle extends StatefulWidget { class _MihToggleState extends State { late bool togglePosition; + @override + void didUpdateWidget(covariant MihToggle oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.initialPostion != oldWidget.initialPostion) { + setState(() { + togglePosition = widget.initialPostion; + }); + } + } + @override void initState() { super.initState(); - setState(() { - togglePosition = widget.initialPostion; - }); + togglePosition = widget.initialPostion; } @override @@ -51,7 +59,7 @@ class _MihToggleState extends State { ), const SizedBox(width: 10), Switch( - value: widget.initialPostion, + value: togglePosition, trackOutlineColor: WidgetStateProperty.resolveWith( (states) { if (widget.readOnly == true) { @@ -81,7 +89,15 @@ class _MihToggleState extends State { // activeTrackColor: widget.fillColor, // inactiveThumbColor: widget.fillColor, // inactiveTrackColor: widget.secondaryFillColor, - onChanged: widget.readOnly != true ? widget.onChange : null, + // onChanged: widget.readOnly != true ? widget.onChange : null, + onChanged: widget.readOnly != true + ? (newValue) { + setState(() { + togglePosition = newValue; // Update internal state + }); + widget.onChange(newValue); // Call the parent's onChange + } + : null, ), ], ); From 87d1f9faa91922fbe55243f6f9f5a3487882e331 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Fri, 4 Jul 2025 11:54:47 +0200 Subject: [PATCH 13/68] update add business woth mnew fields --- .../profile_business_add.dart | 180 +++++++++++++----- 1 file changed, 133 insertions(+), 47 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart index bea0eeff..ce072c29 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart @@ -56,12 +56,16 @@ class _ProfileBusinessAddState extends State { final locationController = TextEditingController(); final practiceNoController = TextEditingController(); final vatNoController = TextEditingController(); + final websiteController = TextEditingController(); + final ratingController = TextEditingController(); + final missionVisionController = TextEditingController(); ImageProvider? logoPreview; ImageProvider? signaturePreview; PlatformFile? selectedLogo; PlatformFile? selectedSignature; + final ValueNotifier _counter = ValueNotifier(0); final ValueNotifier busType = ValueNotifier(""); final _formKey = GlobalKey(); late String env; @@ -123,6 +127,9 @@ class _ProfileBusinessAddState extends State { contactController.text, locationController.text, logonameController.text, + websiteController.text, + "0", + missionVisionController.text, context, ); print(response.body); @@ -233,6 +240,14 @@ class _ProfileBusinessAddState extends State { ); } + Color getMissionVisionLimitColor(int limit) { + if (_counter.value <= limit) { + return MzanziInnovationHub.of(context)!.theme.secondaryColor(); + } else { + return MzanziInnovationHub.of(context)!.theme.errorColor(); + } + } + MIHBody getBody(double width) { return MIHBody( borderOn: false, @@ -280,10 +295,54 @@ class _ProfileBusinessAddState extends State { inputColor: MzanziInnovationHub.of(context)! .theme .primaryColor(), - controller: regController, + controller: nameController, multiLineInput: false, requiredText: true, - hintText: "Registration No.", + hintText: "Business Name", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10.0), + MihDropdownField( + controller: typeController, + hintText: "Business Type", + dropdownOptions: const ["Doctors Office", "Other"], + editable: true, + enableSearch: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + requiredText: true, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + inputColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + controller: emailController, + multiLineInput: false, + requiredText: true, + hintText: "Business Email", + validator: (value) { + return MihValidationServices().validateEmail(value); + }, + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + inputColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + controller: contactController, + multiLineInput: false, + requiredText: true, + hintText: "Contact Number", validator: (value) { return MihValidationServices().isEmpty(value); }, @@ -296,25 +355,79 @@ class _ProfileBusinessAddState extends State { inputColor: MzanziInnovationHub.of(context)! .theme .primaryColor(), - controller: nameController, + controller: websiteController, multiLineInput: false, - requiredText: true, - hintText: "Business Name", + requiredText: false, + hintText: "Business Website", validator: (value) { - return MihValidationServices().isEmpty(value); + return MihValidationServices() + .validateWebsite(value, false); }, ), - const SizedBox(height: 15.0), - MihDropdownField( - controller: typeController, - hintText: "Business Type", - dropdownOptions: const ["Doctors Office", "Other"], - editable: true, - enableSearch: true, + const SizedBox(height: 10.0), + MihTextFormField( + height: 250, + fillColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + inputColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + controller: missionVisionController, + multiLineInput: true, + requiredText: true, + hintText: "Business Mission & Vision", + validator: (value) { + return MihValidationServices().validateLength( + missionVisionController.text, 256); + }, + ), + SizedBox( + height: 15, + child: ValueListenableBuilder( + valueListenable: _counter, + builder: + (BuildContext context, int value, Widget? child) { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "$value", + style: TextStyle( + color: getMissionVisionLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 5), + Text( + "/256", + style: TextStyle( + color: getMissionVisionLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + ], + ); + }, + ), + ), + const SizedBox(height: 10.0), + + MihTextFormField( + fillColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + inputColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + controller: regController, + multiLineInput: false, + requiredText: true, + hintText: "Registration No.", validator: (value) { return MihValidationServices().isEmpty(value); }, - requiredText: true, ), const SizedBox(height: 10.0), ValueListenableBuilder( @@ -362,38 +475,6 @@ class _ProfileBusinessAddState extends State { }, ), const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MzanziInnovationHub.of(context)! - .theme - .secondaryColor(), - inputColor: MzanziInnovationHub.of(context)! - .theme - .primaryColor(), - controller: contactController, - multiLineInput: false, - requiredText: true, - hintText: "Contact Number", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10.0), - MihTextFormField( - fillColor: MzanziInnovationHub.of(context)! - .theme - .secondaryColor(), - inputColor: MzanziInnovationHub.of(context)! - .theme - .primaryColor(), - controller: emailController, - multiLineInput: false, - requiredText: true, - hintText: "Business Email", - validator: (value) { - return MihValidationServices().validateEmail(value); - }, - ), - const SizedBox(height: 10.0), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ @@ -573,6 +654,7 @@ class _ProfileBusinessAddState extends State { @override void initState() { + super.initState(); typeController.addListener(typeSelected); setState(() { fnameController.text = widget.signedInUser.fname; @@ -584,7 +666,11 @@ class _ProfileBusinessAddState extends State { } else { env = "Dev"; } - super.initState(); + missionVisionController.addListener(() { + setState(() { + _counter.value = missionVisionController.text.characters.length; + }); + }); } @override From 95c53acb5622407418761b63ce2d108afe7659a8 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Fri, 4 Jul 2025 11:58:52 +0200 Subject: [PATCH 14/68] change position of counter --- .../personal_profile/package_tools/mih_personal_profile.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b72400e0..8db718f2 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 @@ -311,6 +311,7 @@ class _MihPersonalProfileState extends State { SizedBox( height: 15, child: ValueListenableBuilder( + valueListenable: _counter, builder: (BuildContext context, int value, Widget? child) { return Row( @@ -335,7 +336,6 @@ class _MihPersonalProfileState extends State { ], ); }, - valueListenable: _counter, ), ), const SizedBox(height: 10.0), From a24a694db908afab630ba2f72b3382dbb6204f87 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Fri, 4 Jul 2025 13:05:15 +0200 Subject: [PATCH 15/68] update api with new fields --- backend/routers/business.py | 73 ++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/backend/routers/business.py b/backend/routers/business.py index 6bdcf54c..97057d88 100644 --- a/backend/routers/business.py +++ b/backend/routers/business.py @@ -27,6 +27,9 @@ class businessInsertRequest(BaseModel): gps_location: str practice_no: str vat_no: str + website: str + rating: str + mission_vision: str class businessUpdateRequest(BaseModel): business_id: str @@ -41,6 +44,22 @@ class businessUpdateRequest(BaseModel): practice_no: str vat_no: str +class businessUpdateRequestV2(BaseModel): + business_id: str + Name: str + type: str + registration_no: str + logo_name: str + logo_path: str + contact_no: str + bus_email: str + gps_location: str + practice_no: str + vat_no: str + website: str + rating: str + mission_vision: str + # Get List of all files @router.get("/business/business_id/{business_id}", tags=["MIH Business"]) @@ -51,6 +70,7 @@ async def read_business_by_business_id(business_id: str, session: SessionContain query += "business.logo_name, business.logo_path, business.contact_no, business.bus_email, " query += "business_users.app_id, business.gps_location, " query += "practice_no, vat_no " + query += "website, rating, mission_vision " query += "FROM business " query += "inner join business_users " query += "on business.business_id=business_users.business_id " @@ -73,6 +93,9 @@ async def read_business_by_business_id(business_id: str, session: SessionContain "gps_location": item[9], "practice_no": item[10], "vat_no": item[11], + "website": item[12], + "rating": item[13], + "mission_vision": item[14], } for item in cursor.fetchall() ] @@ -93,7 +116,8 @@ async def read_business_by_app_id(app_id: str, session: SessionContainer = Depen query = "SELECT business.business_id, business.Name, business.type, business.registration_no, " query += "business.logo_name, business.logo_path, business.contact_no, business.bus_email, " query += "business_users.app_id, business.gps_location, " - query += "practice_no, vat_no " + query += "practice_no, vat_no, " + query += "website, rating, mission_vision " query += "FROM business " query += "inner join business_users " query += "on business.business_id=business_users.business_id " @@ -116,6 +140,9 @@ async def read_business_by_app_id(app_id: str, session: SessionContainer = Depen "gps_location": item[9], "practice_no": item[10], "vat_no": item[11], + "website": item[12], + "rating": item[13], + "mission_vision": item[14], } for item in cursor.fetchall() ] @@ -132,8 +159,8 @@ async def insert_business_details(itemRequest : businessInsertRequest, session: db = database.dbConnection.dbAppDataConnect() cursor = db.cursor() query = "insert into business " - query += "(business_id, Name, type, registration_no, logo_name, logo_path, contact_no, bus_email, gps_location, practice_no, vat_no) " - query += "values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" + query += "(business_id, Name, type, registration_no, logo_name, logo_path, contact_no, bus_email, gps_location, practice_no, vat_no, website, rating, mission_vision) " + query += "values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)" uuidString = str(uuid.uuid1()) userData = (uuidString, itemRequest.Name, @@ -145,9 +172,12 @@ async def insert_business_details(itemRequest : businessInsertRequest, session: itemRequest.bus_email, itemRequest.gps_location, itemRequest.practice_no, - itemRequest.vat_no) + itemRequest.vat_no, + itemRequest.website, + itemRequest.rating, + itemRequest.mission_vision, + ) try: - print(query) print(userData) cursor.execute(query, userData) @@ -187,4 +217,37 @@ async def Update_Business_details(itemRequest : businessUpdateRequest, session: db.commit() cursor.close() db.close() + return {"message": "Successfully Updated Record"} + +@router.put("/business/update/v2/", tags=["MIH Business"]) +async def Update_Business_details(itemRequest : businessUpdateRequestV2, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session()) + db = database.dbConnection.dbAppDataConnect() + # print(itemRequest.gps_location) + cursor = db.cursor() + query = "update business " + query += "set Name=%s, type=%s, registration_no=%s, logo_name=%s, logo_path=%s, contact_no=%s, bus_email=%s, gps_location=%s, practice_no=%s, vat_no=%s, website=%s, rating=%s, mission_vision=%s " + query += "where business_id=%s" + userData = (itemRequest.Name, + itemRequest.type, + itemRequest.registration_no, + itemRequest.logo_name, + itemRequest.logo_path, + itemRequest.contact_no, + itemRequest.bus_email, + itemRequest.gps_location, + itemRequest.practice_no, + itemRequest.vat_no, + itemRequest.website, + itemRequest.rating, + itemRequest.mission_vision, + itemRequest.business_id, + ) + try: + cursor.execute(query, userData) + except Exception as error: + raise HTTPException(status_code=404, detail=error) + #return {"query": query, "message": error} + db.commit() + cursor.close() + db.close() return {"message": "Successfully Updated Record"} \ No newline at end of file From 1a14868bcf59dab0de27efae1d4ba8719d2e6873 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Fri, 4 Jul 2025 13:05:24 +0200 Subject: [PATCH 16/68] add new fields to objects --- Frontend/lib/mih_components/mih_objects/business.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Frontend/lib/mih_components/mih_objects/business.dart b/Frontend/lib/mih_components/mih_objects/business.dart index cafded10..2939ba24 100644 --- a/Frontend/lib/mih_components/mih_objects/business.dart +++ b/Frontend/lib/mih_components/mih_objects/business.dart @@ -12,6 +12,9 @@ class Business { final String gps_location; final String practice_no; final String vat_no; + final String website; + final String rating; + final String mission_vision; const Business( this.business_id, @@ -26,6 +29,9 @@ class Business { this.gps_location, this.practice_no, this.vat_no, + this.website, + this.rating, + this.mission_vision, ); factory Business.fromJson(dynamic json) { @@ -42,6 +48,9 @@ class Business { json['gps_location'], json['practice_no'], json['vat_no'], + json['website'], + json['rating'], + json['mission_vision'], ); } } From 0014a3bda312fb8c2fc6b63278d4eefa2c24a9fd Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Fri, 4 Jul 2025 13:05:40 +0200 Subject: [PATCH 17/68] add website validation --- .../lib/mih_services/mih_validation_services.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Frontend/lib/mih_services/mih_validation_services.dart b/Frontend/lib/mih_services/mih_validation_services.dart index 36595cee..d7085268 100644 --- a/Frontend/lib/mih_services/mih_validation_services.dart +++ b/Frontend/lib/mih_services/mih_validation_services.dart @@ -16,6 +16,18 @@ class MihValidationServices { return null; } + String? validateWebsite(String? website, bool required) { + final websiteRegex = RegExp( + r'^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$'); + if (!required && website!.isEmpty) { + return null; + } + if (!websiteRegex.hasMatch(website!)) { + return "Invalid Website Format"; + } + return null; + } + String? validateEmail(String? email) { if (email == null || email.isEmpty) { return "Email is required"; From 2c2a4885851a932df3cbc43cd383efb44deee0d1 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Fri, 4 Jul 2025 13:05:54 +0200 Subject: [PATCH 18/68] update business services with new fields --- .../mih_business_details_services.dart | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/Frontend/lib/mih_services/mih_business_details_services.dart b/Frontend/lib/mih_services/mih_business_details_services.dart index 2ca27ed4..aa469d5f 100644 --- a/Frontend/lib/mih_services/mih_business_details_services.dart +++ b/Frontend/lib/mih_services/mih_business_details_services.dart @@ -38,6 +38,9 @@ class MihBusinessDetailsServices { String businessPhoneNumber, String businessLocation, String businessLogoFilename, + String businessWebsite, + String businessRating, + String businessMissionVision, BuildContext context, ) async { showDialog( @@ -62,12 +65,67 @@ class MihBusinessDetailsServices { "gps_location": businessLocation, "practice_no": businessPracticeNo, "vat_no": businessVatNo, + "website": businessWebsite, + "rating": businessRating, + "mission_vision": businessMissionVision, }), ); Navigator.of(context).pop(); return response; } + Future updateBusinessDetailsV2( + String business_id, + String business_name, + String business_type, + String business_registration_no, + String business_practice_no, + String business_vat_no, + String business_email, + String business_phone_number, + String business_location, + String business_logo_name, + String businessWebsite, + String businessRating, + String businessMissionVision, + BuildContext context, + ) async { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle(); + }, + ); + var response = await http.put( + Uri.parse("${AppEnviroment.baseApiUrl}/business/update/v2/"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + body: jsonEncode({ + "business_id": business_id, + "Name": business_name, + "type": business_type, + "registration_no": business_registration_no, + "logo_name": business_logo_name, + "logo_path": "$business_id/business_files/$business_logo_name", + "contact_no": business_phone_number, + "bus_email": business_email, + "gps_location": business_location, + "practice_no": business_practice_no, + "vat_no": business_vat_no, + "website": businessWebsite, + "rating": businessRating, + "mission_vision": businessMissionVision, + }), + ); + Navigator.of(context).pop(); + if (response.statusCode == 200) { + return 200; + } else { + return 500; + } + } + Future updateBusinessDetails( String business_id, String business_name, @@ -110,7 +168,6 @@ class MihBusinessDetailsServices { if (response.statusCode == 200) { return 200; } else { - internetConnectionPopUp(context); return 500; } } From 618408c185eb6511070c7e34349c928e361d635b Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Fri, 4 Jul 2025 13:06:17 +0200 Subject: [PATCH 19/68] update business details profile udpate --- .../package_tools/mih_business_details.dart | 184 +++++++++++++----- 1 file changed, 136 insertions(+), 48 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart index a0e0bcf2..58bd6d5a 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart @@ -47,13 +47,17 @@ class _MihBusinessDetailsState extends State { final contactController = TextEditingController(); final emailController = TextEditingController(); final locationController = TextEditingController(); + final websiteController = TextEditingController(); + final ratingController = TextEditingController(); + final missionVisionController = TextEditingController(); final _formKey = GlobalKey(); + final ValueNotifier _counter = ValueNotifier(0); late String env; Future submitForm() async { if (isFormFilled()) { int statusCode = 0; - statusCode = await MihBusinessDetailsServices().updateBusinessDetails( + statusCode = await MihBusinessDetailsServices().updateBusinessDetailsV2( widget.arguments.business!.business_id, nameController.text, typeController.text, @@ -64,6 +68,9 @@ class _MihBusinessDetailsState extends State { contactController.text, locationController.text, fileNameController.text, + websiteController.text, + ratingController.text.isEmpty ? "0" : ratingController.text, + missionVisionController.text, context, ); if (statusCode == 200) { @@ -253,10 +260,55 @@ class _MihBusinessDetailsState extends State { inputColor: MzanziInnovationHub.of(context)! .theme .primaryColor(), - controller: regController, + controller: nameController, multiLineInput: false, requiredText: true, - hintText: "Registration No.", + hintText: "Business Name", + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + ), + const SizedBox(height: 10), + MihDropdownField( + controller: typeController, + hintText: "Business Type", + dropdownOptions: const ["Doctors Office", "Other"], + editable: true, + enableSearch: true, + validator: (value) { + return MihValidationServices().isEmpty(value); + }, + requiredText: true, + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + inputColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + controller: emailController, + multiLineInput: false, + requiredText: true, + hintText: "Business Email", + validator: (value) { + return MihValidationServices() + .validateEmail(value); + }, + ), + const SizedBox(height: 10), + MihTextFormField( + fillColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + inputColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + controller: contactController, + multiLineInput: false, + requiredText: true, + hintText: "Contact Number", validator: (value) { return MihValidationServices().isEmpty(value); }, @@ -269,25 +321,78 @@ class _MihBusinessDetailsState extends State { inputColor: MzanziInnovationHub.of(context)! .theme .primaryColor(), - controller: nameController, + controller: websiteController, multiLineInput: false, - requiredText: true, - hintText: "Business Name", + requiredText: false, + hintText: "Business Website", validator: (value) { - return MihValidationServices().isEmpty(value); + return MihValidationServices() + .validateWebsite(value, false); }, ), - const SizedBox(height: 15), - MihDropdownField( - controller: typeController, - hintText: "Business Type", - dropdownOptions: const ["Doctors Office", "Other"], - editable: true, - enableSearch: true, + const SizedBox(height: 10), + MihTextFormField( + height: 250, + fillColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + inputColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + controller: missionVisionController, + multiLineInput: true, + requiredText: true, + hintText: "Business Mission & Vision", + validator: (value) { + return MihValidationServices().validateLength( + missionVisionController.text, 256); + }, + ), + SizedBox( + height: 15, + child: ValueListenableBuilder( + valueListenable: _counter, + builder: (BuildContext context, int value, + Widget? child) { + return Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + "$value", + style: TextStyle( + color: getMissionVisionLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 5), + Text( + "/256", + style: TextStyle( + color: getMissionVisionLimitColor(256), + fontWeight: FontWeight.bold, + ), + ), + ], + ); + }, + ), + ), + const SizedBox(height: 10.0), + MihTextFormField( + fillColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + inputColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + controller: regController, + multiLineInput: false, + requiredText: true, + hintText: "Registration No.", validator: (value) { return MihValidationServices().isEmpty(value); }, - requiredText: true, ), const SizedBox(height: 10), MihTextFormField( @@ -324,39 +429,6 @@ class _MihBusinessDetailsState extends State { }, ), const SizedBox(height: 10), - MihTextFormField( - fillColor: MzanziInnovationHub.of(context)! - .theme - .secondaryColor(), - inputColor: MzanziInnovationHub.of(context)! - .theme - .primaryColor(), - controller: contactController, - multiLineInput: false, - requiredText: true, - hintText: "Contact Number", - validator: (value) { - return MihValidationServices().isEmpty(value); - }, - ), - const SizedBox(height: 10), - MihTextFormField( - fillColor: MzanziInnovationHub.of(context)! - .theme - .secondaryColor(), - inputColor: MzanziInnovationHub.of(context)! - .theme - .primaryColor(), - controller: emailController, - multiLineInput: false, - requiredText: true, - hintText: "Business Email", - validator: (value) { - return MihValidationServices() - .validateEmail(value); - }, - ), - const SizedBox(height: 10), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ @@ -442,6 +514,14 @@ class _MihBusinessDetailsState extends State { )); } + Color getMissionVisionLimitColor(int limit) { + if (_counter.value <= limit) { + return MzanziInnovationHub.of(context)!.theme.secondaryColor(); + } else { + return MzanziInnovationHub.of(context)!.theme.errorColor(); + } + } + @override void dispose() { super.dispose(); @@ -471,12 +551,20 @@ class _MihBusinessDetailsState extends State { contactController.text = widget.arguments.business!.contact_no; emailController.text = widget.arguments.business!.bus_email; locationController.text = widget.arguments.business!.gps_location; + websiteController.text = widget.arguments.business!.website; + ratingController.text = widget.arguments.business!.rating; + missionVisionController.text = widget.arguments.business!.mission_vision; }); if (AppEnviroment.getEnv() == "Prod") { env = "Prod"; } else { env = "Dev"; } + missionVisionController.addListener(() { + setState(() { + _counter.value = missionVisionController.text.characters.length; + }); + }); } @override From 501283716efe91abeb903eb985f9f110b58a3d89 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Fri, 4 Jul 2025 13:39:42 +0200 Subject: [PATCH 20/68] add mission and vision to profile --- .../package_tools/mih_business_details.dart | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart index 58bd6d5a..7504225a 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart @@ -618,10 +618,9 @@ class _MihBusinessDetailsState extends State { ), ), ), - // Center( + // FittedBox( // child: Text( - // "*DEMO TEXT* This would be the bio of the user telling us a bit about themself and let. This would be the bio of the user telling us a bit about themself and let. This would be the bio of the user telling us a bit about themself", - // textAlign: TextAlign.center, + // "Mission & Vision", // style: TextStyle( // fontSize: 15, // fontWeight: FontWeight.bold, @@ -631,6 +630,24 @@ class _MihBusinessDetailsState extends State { // ), // ), // ), + Center( + child: SizedBox( + width: 700, + child: Text( + widget.arguments.business!.mission_vision.isNotEmpty + ? widget.arguments.business!.mission_vision + : "No Mission & Vision added yet", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + ), + ), + ), + ), const SizedBox(height: 20), SizedBox( width: 700, @@ -640,8 +657,7 @@ class _MihBusinessDetailsState extends State { email: widget.arguments.business!.bus_email, gpsLocation: widget.arguments.business!.gps_location, //To-Do: Add the business Website - website: - "https://app.mzansi-innovation-hub.co.za/privacy.html", + website: widget.arguments.business!.website, ), ), const SizedBox(height: 30.0), From 02c4ceab5d29e781fbcea277142f7106984add25 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Fri, 4 Jul 2025 13:40:12 +0200 Subject: [PATCH 21/68] new error messages and add website launch --- .../components/mih_business_card.dart | 199 ++++++++++-------- 1 file changed, 108 insertions(+), 91 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart index 6cba0fe2..f9071f43 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart @@ -8,14 +8,14 @@ class MihBusinessCard extends StatefulWidget { final String cellNumber; final String email; final String gpsLocation; - final String website; + final String? website; const MihBusinessCard({ super.key, required this.businessName, required this.cellNumber, required this.email, required this.gpsLocation, - required this.website, + this.website, }); @override @@ -35,15 +35,17 @@ class _MihBusinessCardState extends State { alertIcon: Icon( Icons.warning_rounded, size: 100, + color: MzanziInnovationHub.of(context)!.theme.errorColor(), ), alertTitle: "Error Making Call", alertBody: Column( children: [ Text( - "Unable to lauch phone to call ${widget.cellNumber}", + "We couldn't open your phone app to call ${widget.cellNumber}. To fix this, make sure you have a phone application installed and it's set as your default dialer.", style: TextStyle( - color: - MzanziInnovationHub.of(context)!.theme.errorColor(), + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), fontSize: 15, ), ), @@ -83,15 +85,17 @@ class _MihBusinessCardState extends State { alertIcon: Icon( Icons.warning_rounded, size: 100, + color: MzanziInnovationHub.of(context)!.theme.errorColor(), ), alertTitle: "Error Creating Email", alertBody: Column( children: [ Text( - "Unable to lauch email to ${widget.email}", + "We couldn't launch your email app to send a message to ${widget.email}. To fix this, please confirm that you have an email application installed and that it's set as your default.", style: TextStyle( - color: - MzanziInnovationHub.of(context)!.theme.errorColor(), + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), fontSize: 15, ), ), @@ -115,8 +119,6 @@ class _MihBusinessCardState extends State { if (await canLaunchUrl(googleMapsUrl)) { await launchUrl(googleMapsUrl); } else { - print( - 'Could not launch Google Maps. Make sure the Google Maps app is installed or an internet connection is available.'); showDialog( context: context, builder: (context) { @@ -124,15 +126,17 @@ class _MihBusinessCardState extends State { alertIcon: Icon( Icons.warning_rounded, size: 100, + color: MzanziInnovationHub.of(context)!.theme.errorColor(), ), alertTitle: "Error Creating Maps", alertBody: Column( children: [ Text( - "Unable to lauch maps to ${widget.businessName}", + "There was an issue opening maps for ${widget.businessName}. This usually happens if you don't have a maps app installed or it's not set as your default. Please install one to proceed.", style: TextStyle( - color: - MzanziInnovationHub.of(context)!.theme.errorColor(), + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), fontSize: 15, ), ), @@ -151,15 +155,17 @@ class _MihBusinessCardState extends State { alertIcon: Icon( Icons.warning_rounded, size: 100, + color: MzanziInnovationHub.of(context)!.theme.errorColor(), ), alertTitle: "Error Creating Maps", alertBody: Column( children: [ Text( - "Unable to lauch maps to ${widget.businessName}", + "There was an issue opening maps for ${widget.businessName}. This usually happens if you don't have a maps app installed or it's not set as your default. Please install one to proceed.", style: TextStyle( - color: - MzanziInnovationHub.of(context)!.theme.errorColor(), + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), fontSize: 15, ), ), @@ -171,66 +177,74 @@ class _MihBusinessCardState extends State { } } - // Future _launchWebsite(String urlString) async { - // final Uri url = Uri.parse(urlString); - // try { - // if (await canLaunchUrl(url)) { - // await launchUrl(url); - // } else { - // print('Could not launch $urlString'); - // showDialog( - // context: context, - // builder: (context) { - // return MihPackageAlert( - // alertIcon: Icon( - // Icons.warning_rounded, - // size: 100, - // ), - // alertTitle: "Error Opening Website", - // alertBody: Column( - // children: [ - // Text( - // "Unable to lauch ${widget.businessName}", - // style: TextStyle( - // color: - // MzanziInnovationHub.of(context)!.theme.errorColor(), - // fontSize: 15, - // ), - // ), - // ], - // ), - // alertColour: - // MzanziInnovationHub.of(context)!.theme.errorColor(), - // ); - // }); - // } - // } catch (e) { - // showDialog( - // context: context, - // builder: (context) { - // return MihPackageAlert( - // alertIcon: Icon( - // Icons.warning_rounded, - // size: 100, - // ), - // alertTitle: "Error Opening Website", - // alertBody: Column( - // children: [ - // Text( - // "Unable to lauch ${widget.businessName}", - // style: TextStyle( - // color: - // MzanziInnovationHub.of(context)!.theme.errorColor(), - // fontSize: 15, - // ), - // ), - // ], - // ), - // alertColour: MzanziInnovationHub.of(context)!.theme.errorColor(), - // ); - // }); - // } - // } + Future _launchWebsite(String urlString) async { + String newUrl = urlString; + if (!newUrl.startsWith("https://")) { + newUrl = "https://$urlString"; + } + final Uri url = Uri.parse(newUrl); + try { + if (await canLaunchUrl(url)) { + await launchUrl(url); + } else { + print('Could not launch $urlString'); + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.warning_rounded, + size: 100, + color: MzanziInnovationHub.of(context)!.theme.errorColor(), + ), + alertTitle: "Error Opening Website", + alertBody: Column( + children: [ + Text( + "We couldn't open the link to $newUrl. To view this website, please ensure you have a web browser installed and set as your default.", + style: TextStyle( + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + fontSize: 15, + ), + ), + ], + ), + alertColour: + MzanziInnovationHub.of(context)!.theme.errorColor(), + ); + }); + } + } catch (e) { + showDialog( + context: context, + builder: (context) { + return MihPackageAlert( + alertIcon: Icon( + Icons.warning_rounded, + size: 100, + color: MzanziInnovationHub.of(context)!.theme.errorColor(), + ), + alertTitle: "Error Opening Website", + alertBody: Column( + children: [ + Text( + "We couldn't open the link to $newUrl. To view this website, please ensure you have a web browser installed and set as your default.", + style: TextStyle( + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + fontSize: 15, + ), + ), + ], + ), + alertColour: MzanziInnovationHub.of(context)!.theme.errorColor(), + ); + }); + } + } Widget _buildContactInfo( String label, @@ -364,21 +378,24 @@ class _MihBusinessCardState extends State { ); }, ), - // Padding( - // padding: const EdgeInsets.symmetric(horizontal: 10.0), - // child: Divider( - // color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - // ), - // ), - // _buildContactInfo( - // "Website", - // "Find out more about us.", - // Icons.vpn_lock, - // const Color(0xffd67d8a), - // () { - // _launchWebsite(widget.website); - // }, - // ), + Visibility( + visible: widget.website != null, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10.0), + child: Divider( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ), + ), + _buildContactInfo( + "Website", + "Find out more about us.", + Icons.vpn_lock, + const Color(0xffd67d8a), + () { + _launchWebsite(widget.website!); + }, + ), // Padding( // padding: const EdgeInsets.symmetric(horizontal: 10.0), // child: Divider( From c1b31a3912ff30aba4efc98f093438cc3c4978ba Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Mon, 7 Jul 2025 18:32:43 +0200 Subject: [PATCH 22/68] Dispose new controllers --- .../business_profile/package_tools/mih_business_details.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart index 7504225a..de8e4ab2 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart @@ -534,6 +534,9 @@ class _MihBusinessDetailsState extends State { contactController.dispose(); emailController.dispose(); locationController.dispose(); + websiteController.dispose(); + ratingController.dispose(); + missionVisionController.dispose(); imageFile = null; } From ea068e4016a2fab4ff35f68ab73a1fc274761931 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Mon, 7 Jul 2025 18:32:51 +0200 Subject: [PATCH 23/68] Dispose new controllers --- .../personal_profile/package_tools/mih_personal_profile.dart | 1 + 1 file changed, 1 insertion(+) 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 8db718f2..e64b8d95 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 @@ -393,6 +393,7 @@ class _MihPersonalProfileState extends State { usernameController.dispose(); fnameController.dispose(); lnameController.dispose(); + purposeController.dispose(); super.dispose(); } From 8b5840d0a3db012cca00a3695dc9416b172f837e Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Mon, 7 Jul 2025 20:09:46 +0200 Subject: [PATCH 24/68] Add appuser as param to test package --- .../mih_package_components/Example/package_test.dart | 11 +++++++++-- .../Example/package_tools/package_tool_one.dart | 12 +++++++++++- Frontend/lib/mih_config/mih_routeGenerator.dart | 12 +++++++----- .../mih_home/package_tools/mih_personal_home.dart | 2 +- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Frontend/lib/mih_components/mih_package_components/Example/package_test.dart b/Frontend/lib/mih_components/mih_package_components/Example/package_test.dart index 20f4a0a1..221fce33 100644 --- a/Frontend/lib/mih_components/mih_package_components/Example/package_test.dart +++ b/Frontend/lib/mih_components/mih_package_components/Example/package_test.dart @@ -1,4 +1,5 @@ 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_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_alert.dart'; @@ -9,7 +10,11 @@ import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart' import 'package:flutter/material.dart'; class PackageTest extends StatefulWidget { - const PackageTest({super.key}); + final AppUser user; + const PackageTest({ + super.key, + required this.user, + }); @override State createState() => _PackageTestState(); @@ -111,7 +116,9 @@ class _PackageTestState extends State { List getToolBody() { List toolBodies = [ - const PackageToolOne(), + PackageToolOne( + user: widget.user, + ), const PackageToolTwo(), ]; return toolBodies; diff --git a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart index 4290ae18..f3ad21d9 100644 --- a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart +++ b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart @@ -2,7 +2,9 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_speed_dial/flutter_speed_dial.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_banner_ad.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_personal_profile_preview.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; @@ -25,7 +27,11 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; class PackageToolOne extends StatefulWidget { - const PackageToolOne({super.key}); + final AppUser user; + const PackageToolOne({ + super.key, + required this.user, + }); @override State createState() => _PackageToolOneState(); @@ -166,6 +172,10 @@ class _PackageToolOneState extends State { ], ), const SizedBox(height: 20), + MihPersonalProfilePreview( + user: widget.user, + ), + const SizedBox(height: 10), MihBusinessCard( businessName: "Mzansi Innovation Hub", cellNumber: "0788300006", diff --git a/Frontend/lib/mih_config/mih_routeGenerator.dart b/Frontend/lib/mih_config/mih_routeGenerator.dart index 17fd4536..38eb52bd 100644 --- a/Frontend/lib/mih_config/mih_routeGenerator.dart +++ b/Frontend/lib/mih_config/mih_routeGenerator.dart @@ -298,11 +298,13 @@ class RouteGenerator { break; case AppRoutes.packageDevTest: - // No arguments expected for this test route - return MaterialPageRoute( - settings: settings, - builder: (_) => const PackageTest(), - ); + if (args is AppUser) { + return MaterialPageRoute( + settings: settings, + builder: (_) => PackageTest(user: args), + ); + } + break; default: // If no match is found, fall through to the error route diff --git a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart index 00ba3e31..68c67af9 100644 --- a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart +++ b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart @@ -162,7 +162,7 @@ class _MihPersonalHomeState extends State onTap: () { Navigator.of(context).pushNamed( '/package-dev', - //arguments: widget.signedInUser, + arguments: widget.signedInUser, ); }, appName: "Test", From 4fa52b8ca77018224ada86600b7c0b1ff4266aaa Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Mon, 7 Jul 2025 20:10:12 +0200 Subject: [PATCH 25/68] create a new widget to display a personal profile preview --- .../mih_personal_profile_preview.dart | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart diff --git a/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart b/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart new file mode 100644 index 00000000..6d26dd0d --- /dev/null +++ b/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart @@ -0,0 +1,92 @@ +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; + +class MihPersonalProfilePreview extends StatefulWidget { + final AppUser user; + const MihPersonalProfilePreview({ + super.key, + required this.user, + }); + + @override + State createState() => + _MihPersonalProfilePreviewState(); +} + +class _MihPersonalProfilePreviewState extends State { + late Future futureImageUrl; + // String imageUrl = ""; + PlatformFile? file; + + @override + void initState() { + super.initState(); + futureImageUrl = + MihFileApi.getMinioFileUrl(widget.user.pro_pic_path, context); + } + + @override + Widget build(BuildContext context) { + double profilePictureWidth = 60; + return Row( + children: [ + FutureBuilder( + future: futureImageUrl, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == ConnectionState.done && + asyncSnapshot.hasData) { + return MihCircleAvatar( + imageFile: NetworkImage(asyncSnapshot.requireData), + width: profilePictureWidth, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + backgroundColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.mihLogo, + size: profilePictureWidth, + ); + } + }), + const SizedBox(width: 15), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "@${widget.user.username}", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + Text( + "${widget.user.fname} ${widget.user.lname}", + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 15, + ), + ), + Text( + widget.user.type.toUpperCase(), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 10, + ), + ), + ], + ) + ], + ); + } +} From ec251bba8683aa95ed909649179394615ff341fa Mon Sep 17 00:00:00 2001 From: yaso Date: Tue, 8 Jul 2025 10:35:07 +0200 Subject: [PATCH 26/68] Make website action visibility dynamic --- .../components/mih_business_card.dart | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart index f9071f43..5c531b57 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart @@ -379,7 +379,7 @@ class _MihBusinessCardState extends State { }, ), Visibility( - visible: widget.website != null, + visible: widget.website != null && widget.website! != "", child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10.0), child: Divider( @@ -387,14 +387,17 @@ class _MihBusinessCardState extends State { ), ), ), - _buildContactInfo( - "Website", - "Find out more about us.", - Icons.vpn_lock, - const Color(0xffd67d8a), - () { - _launchWebsite(widget.website!); - }, + Visibility( + visible: widget.website != null && widget.website! != "", + child: _buildContactInfo( + "Website", + "Find out more about us.", + Icons.vpn_lock, + const Color(0xffd67d8a), + () { + _launchWebsite(widget.website!); + }, + ), ), // Padding( // padding: const EdgeInsets.symmetric(horizontal: 10.0), From 00a5c097bed1d7141605d12c7a026acee199a9be Mon Sep 17 00:00:00 2001 From: yaso Date: Tue, 8 Jul 2025 14:01:06 +0200 Subject: [PATCH 27/68] remove load indicator from service --- .../lib/mih_services/mih_location_services.dart | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/Frontend/lib/mih_services/mih_location_services.dart b/Frontend/lib/mih_services/mih_location_services.dart index 2b884e17..2ea3172c 100644 --- a/Frontend/lib/mih_services/mih_location_services.dart +++ b/Frontend/lib/mih_services/mih_location_services.dart @@ -1,4 +1,3 @@ -import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import '../mih_components/mih_pop_up_messages/mih_error_message.dart'; @@ -14,29 +13,20 @@ class MIHLocationAPI { ///if user has blocked permission (denied or denied forver), user will get error pop up. ///if user has granted permission (while in use), function will return Position object. Future getGPSPosition(BuildContext context) async { - showDialog( - context: context, - builder: (context) { - return const Mihloadingcircle(); - }, - ); - //Check the type of permission granted + print("Before checkPermission"); // Debug LocationPermission permission = await Geolocator.checkPermission(); + print("After checkPermission: $permission"); // Debug if (permission == LocationPermission.denied) { - //First time user (auto denied pernission) request permission from user permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) { - //User denied permission showPermissionError(context); return null; } else if (permission == LocationPermission.deniedForever) { - //User denied permission Forever showPermissionError(context); return null; } else { Position location = await Geolocator.getCurrentPosition( locationSettings: locationSettings); - //print(location); return location; } } else if (permission == LocationPermission.deniedForever) { @@ -45,8 +35,6 @@ class MIHLocationAPI { } else { Position location = await Geolocator.getCurrentPosition( locationSettings: locationSettings); - //print(location); - Navigator.of(context).pop(); return location; } } From 4666e809f4982b49c5192b512209634cae485be2 Mon Sep 17 00:00:00 2001 From: yaso Date: Tue, 8 Jul 2025 14:01:29 +0200 Subject: [PATCH 28/68] add loading indicator to set button push --- .../package_tools/mih_business_details.dart | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart index de8e4ab2..10795ed2 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart @@ -4,6 +4,7 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.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_business_card.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; @@ -449,6 +450,12 @@ class _MihBusinessDetailsState extends State { const SizedBox(width: 10.0), MihButton( onPressed: () { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle(); + }, + ); MIHLocationAPI() .getGPSPosition(context) .then((position) { @@ -458,6 +465,8 @@ class _MihBusinessDetailsState extends State { "${position.latitude}, ${position.longitude}"; }); } + //Dismiss loading indicator + Navigator.of(context).pop(); }); }, buttonColor: MzanziInnovationHub.of(context)! From 0c98ad90a6dad76d8265b29e64aa8c65ca0328a1 Mon Sep 17 00:00:00 2001 From: yaso Date: Wed, 9 Jul 2025 11:11:43 +0200 Subject: [PATCH 29/68] add test args --- .../lib/mih_components/mih_objects/arguments.dart | 10 ++++++++++ .../mih_package_components/Example/package_test.dart | 12 ++++++++---- Frontend/lib/mih_config/mih_routeGenerator.dart | 4 ++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Frontend/lib/mih_components/mih_objects/arguments.dart b/Frontend/lib/mih_components/mih_objects/arguments.dart index 3e4d82e3..5d85ec92 100644 --- a/Frontend/lib/mih_components/mih_objects/arguments.dart +++ b/Frontend/lib/mih_components/mih_objects/arguments.dart @@ -217,3 +217,13 @@ class MzansiAiArguments { this.startUpQuestion, ); } + +class TestArguments { + final AppUser user; + final Business? business; + + TestArguments( + this.user, + this.business, + ); +} diff --git a/Frontend/lib/mih_components/mih_package_components/Example/package_test.dart b/Frontend/lib/mih_components/mih_package_components/Example/package_test.dart index 221fce33..e54b27e8 100644 --- a/Frontend/lib/mih_components/mih_package_components/Example/package_test.dart +++ b/Frontend/lib/mih_components/mih_package_components/Example/package_test.dart @@ -1,5 +1,4 @@ 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_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_alert.dart'; @@ -10,10 +9,14 @@ import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart' import 'package:flutter/material.dart'; class PackageTest extends StatefulWidget { - final AppUser user; + // final AppUser user; + // final Business business; + final TestArguments arguments; const PackageTest({ super.key, - required this.user, + required this.arguments, + // required this.user, + // required this.business, }); @override @@ -117,7 +120,8 @@ class _PackageTestState extends State { List getToolBody() { List toolBodies = [ PackageToolOne( - user: widget.user, + user: widget.arguments.user, + business: widget.arguments.business!, ), const PackageToolTwo(), ]; diff --git a/Frontend/lib/mih_config/mih_routeGenerator.dart b/Frontend/lib/mih_config/mih_routeGenerator.dart index 38eb52bd..b7b36736 100644 --- a/Frontend/lib/mih_config/mih_routeGenerator.dart +++ b/Frontend/lib/mih_config/mih_routeGenerator.dart @@ -298,10 +298,10 @@ class RouteGenerator { break; case AppRoutes.packageDevTest: - if (args is AppUser) { + if (args is TestArguments) { return MaterialPageRoute( settings: settings, - builder: (_) => PackageTest(user: args), + builder: (_) => PackageTest(arguments: args), ); } break; From d34878fc5eee2f61e8dce389a8890faf7669efbd Mon Sep 17 00:00:00 2001 From: yaso Date: Wed, 9 Jul 2025 11:12:24 +0200 Subject: [PATCH 30/68] work from bae --- .../package_tools/package_tool_one.dart | 95 +++++++++++++++++++ .../mih_business_profile_preview.dart | 94 ++++++++++++++++++ .../mih_personal_profile_preview.dart | 2 +- .../mih_home/mih_home_legacy.dart | 4 +- .../package_tools/mih_personal_home.dart | 5 +- .../package_tools/mih_personal_profile.dart | 2 +- .../mih_services/mih_location_services.dart | 10 +- 7 files changed, 204 insertions(+), 8 deletions(-) create mode 100644 Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart diff --git a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart index f3ad21d9..022a2eaa 100644 --- a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart +++ b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart @@ -1,12 +1,16 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_speed_dial/flutter_speed_dial.dart'; +import 'package:geolocator/geolocator.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_banner_ad.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_personal_profile_preview.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; @@ -28,9 +32,11 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ class PackageToolOne extends StatefulWidget { final AppUser user; + final Business business; const PackageToolOne({ super.key, required this.user, + required this.business, }); @override @@ -57,6 +63,8 @@ class _PackageToolOneState extends State { bool switchpositioin = true; final FocusNode searchFocusNode = FocusNode(); final _formKey = GlobalKey(); + late Future myCoordinates; + String myLocation = ""; void showTestFullWindow() { showDialog( @@ -139,6 +147,8 @@ class _PackageToolOneState extends State { // const NetworkImage( // "https://lh3.googleusercontent.com/nW4ZZ89Q1ATz7Ht3nsAVWXL_cwNi4gNusqQZiL60UuuI3FG-VM7bTYDoJ-sUr2kDTdorfQYjxo5PjDM-0MO5rA=s512"); }); + + // myCoordinates = MIHLocationAPI().getGPSPosition(context); } Widget getBody(double width) { @@ -172,10 +182,95 @@ class _PackageToolOneState extends State { ], ), const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Personal Preview", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + ), + ), + ], + ), + const SizedBox(height: 10), MihPersonalProfilePreview( user: widget.user, ), const SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Business Preview", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + ), + ), + ], + ), + const SizedBox(height: 10), + FutureBuilder( + future: MIHLocationAPI().getGPSPosition(context), + builder: (context, asyncSnapshot) { + // print(asyncSnapshot.connectionState); + if (asyncSnapshot.connectionState == + ConnectionState.waiting) { + return Container( + width: 150, + height: 50, + color: Colors.black, + child: Center(child: CircularProgressIndicator()), + ); + } else if (asyncSnapshot.hasError || + !asyncSnapshot.hasData || + asyncSnapshot.data == null) { + return Container( + width: 150, + height: 50, + color: Colors.red, + child: Center(child: Text("Location unavailable")), + ); + } else { + final myLocation = asyncSnapshot.data + .toString() + .replaceAll("Latitude: ", "") + .replaceAll("Longitude: ", ""); + print("My Location is this: $myLocation"); + return MihBusinessProfilePreview( + business: widget.business, + myLocation: myLocation, + ); + } + // // print(asyncSnapshot.requireData); + // if (asyncSnapshot.connectionState == + // ConnectionState.done && + // asyncSnapshot.hasData) { + // print(asyncSnapshot.requireData); + // myLocation = asyncSnapshot.requireData.toString(); + // return MihBusinessProfilePreview( + // business: widget.business, + // myLocation: myLocation, + // ); + // } else { + // return Container( + // width: 150, + // height: 50, + // color: Colors.black, + // ); + // } + }), + const SizedBox(height: 10), MihBusinessCard( businessName: "Mzansi Innovation Hub", cellNumber: "0788300006", diff --git a/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart b/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart new file mode 100644 index 00000000..d661b7b6 --- /dev/null +++ b/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart @@ -0,0 +1,94 @@ +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; + +class MihBusinessProfilePreview extends StatefulWidget { + final Business business; + final String myLocation; + const MihBusinessProfilePreview({ + super.key, + required this.business, + required this.myLocation, + }); + + @override + State createState() => + _MihBusinessProfilePreviewState(); +} + +class _MihBusinessProfilePreviewState extends State { + late Future futureImageUrl; + PlatformFile? file; + + String calculateDistance() { + double distanceInKm = MIHLocationAPI().getDistanceInMeaters( + widget.myLocation, widget.business.gps_location) / + 1000; + return "${distanceInKm.toStringAsFixed(2)} km"; + } + + @override + void initState() { + super.initState(); + futureImageUrl = + MihFileApi.getMinioFileUrl(widget.business.logo_path, context); + } + + @override + Widget build(BuildContext context) { + double profilePictureWidth = 60; + return Row( + children: [ + FutureBuilder( + future: futureImageUrl, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == ConnectionState.done && + asyncSnapshot.hasData) { + return MihCircleAvatar( + imageFile: NetworkImage(asyncSnapshot.requireData), + width: profilePictureWidth, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + backgroundColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.mihLogo, + size: profilePictureWidth, + ); + } + }), + const SizedBox(width: 15), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.business.Name, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + ), + ), + Text( + calculateDistance(), + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 12, + ), + ), + ], + ) + ], + ); + } +} diff --git a/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart b/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart index 6d26dd0d..f8cb958f 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart @@ -64,7 +64,7 @@ class _MihPersonalProfilePreviewState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "@${widget.user.username}", + widget.user.username, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, diff --git a/Frontend/lib/mih_packages/mih_home/mih_home_legacy.dart b/Frontend/lib/mih_packages/mih_home/mih_home_legacy.dart index 17346b69..8ee7050d 100644 --- a/Frontend/lib/mih_packages/mih_home/mih_home_legacy.dart +++ b/Frontend/lib/mih_packages/mih_home/mih_home_legacy.dart @@ -902,8 +902,8 @@ class _MIHHomeLegacyState extends State { MIHLocationAPI().getGPSPosition(context).then((position) { if (position != null) { print(position); - print( - "Distance: ${MIHLocationAPI().getDistanceInMeaters(position, position)}m"); + // print( + // "Distance: ${MIHLocationAPI().getDistanceInMeaters(position, position)}m"); } }); }, diff --git a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart index 68c67af9..e1747155 100644 --- a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart +++ b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart @@ -162,7 +162,10 @@ class _MihPersonalHomeState extends State onTap: () { Navigator.of(context).pushNamed( '/package-dev', - arguments: widget.signedInUser, + arguments: TestArguments( + widget.signedInUser, + widget.business, + ), ); }, appName: "Test", 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 e64b8d95..df1b6575 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 @@ -468,7 +468,7 @@ class _MihPersonalProfileState extends State { ), FittedBox( child: Text( - "@${widget.arguments.signedInUser.username}", + widget.arguments.signedInUser.username, style: TextStyle( fontSize: 35, fontWeight: FontWeight.bold, diff --git a/Frontend/lib/mih_services/mih_location_services.dart b/Frontend/lib/mih_services/mih_location_services.dart index 2ea3172c..4cdc0848 100644 --- a/Frontend/lib/mih_services/mih_location_services.dart +++ b/Frontend/lib/mih_services/mih_location_services.dart @@ -39,9 +39,13 @@ class MIHLocationAPI { } } - double getDistanceInMeaters(Position startPosition, Position endPosition) { - return Geolocator.distanceBetween(startPosition.latitude, - startPosition.longitude, endPosition.latitude, endPosition.longitude); + double getDistanceInMeaters(String startPosition, String endPosition) { + double startLatitude = double.parse(startPosition.split(", ")[0]); + double startLogitude = double.parse(startPosition.split(", ")[1]); + double endLatitude = double.parse(endPosition.split(", ")[0]); + double endLogitude = double.parse(endPosition.split(", ")[1]); + return Geolocator.distanceBetween( + startLatitude, startLogitude, endLatitude, endLogitude); } void showPermissionError(BuildContext context) { From df37a3580816a229ee6ceda5a2edba62fd323d59 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Wed, 9 Jul 2025 11:36:09 +0200 Subject: [PATCH 31/68] error message --- .../mih_components/mih_package_components/mih_banner_ad.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Frontend/lib/mih_components/mih_package_components/mih_banner_ad.dart b/Frontend/lib/mih_components/mih_package_components/mih_banner_ad.dart index b84bc754..d8c60c87 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_banner_ad.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_banner_ad.dart @@ -30,7 +30,8 @@ class _MihBannerAdState extends State { onAdFailedToLoad: (ad, err) { debugPrint('BannerAd failed to load: $err'); setState(() { - errorMessage = 'Failed to load ad: ${err.message}'; + errorMessage = + 'Failed to load ad- Message: ${err.message} Code :${err.code}'; }); ad.dispose(); // Dispose the ad to free resources }, From c8e0709142302aeeea9ea5b8665b02e99a7dbf49 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Wed, 9 Jul 2025 11:36:50 +0200 Subject: [PATCH 32/68] add redatcted when loaded business preview --- .../package_tools/package_tool_one.dart | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart index 022a2eaa..2872da06 100644 --- a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart +++ b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart @@ -29,6 +29,7 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_time_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; +import 'package:redacted/redacted.dart'; class PackageToolOne extends StatefulWidget { final AppUser user; @@ -226,12 +227,19 @@ class _PackageToolOneState extends State { // print(asyncSnapshot.connectionState); if (asyncSnapshot.connectionState == ConnectionState.waiting) { - return Container( - width: 150, - height: 50, - color: Colors.black, - child: Center(child: CircularProgressIndicator()), + return MihBusinessProfilePreview( + business: widget.business, + myLocation: null, + ).redacted( + context: context, + redact: true, ); + // return Container( + // width: 150, + // height: 50, + // // color: Colors.black, + // child: Center(child: CircularProgressIndicator()), + // ); } else if (asyncSnapshot.hasError || !asyncSnapshot.hasData || asyncSnapshot.data == null) { @@ -252,23 +260,6 @@ class _PackageToolOneState extends State { myLocation: myLocation, ); } - // // print(asyncSnapshot.requireData); - // if (asyncSnapshot.connectionState == - // ConnectionState.done && - // asyncSnapshot.hasData) { - // print(asyncSnapshot.requireData); - // myLocation = asyncSnapshot.requireData.toString(); - // return MihBusinessProfilePreview( - // business: widget.business, - // myLocation: myLocation, - // ); - // } else { - // return Container( - // width: 150, - // height: 50, - // color: Colors.black, - // ); - // } }), const SizedBox(height: 10), MihBusinessCard( From 1aa45eccade1414e82f0ae3b32ce04ae96434bec Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Wed, 9 Jul 2025 11:37:12 +0200 Subject: [PATCH 33/68] make mylocation nullable --- .../mih_business_profile_preview.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart b/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart index d661b7b6..eaea39a3 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart @@ -9,7 +9,7 @@ import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; class MihBusinessProfilePreview extends StatefulWidget { final Business business; - final String myLocation; + final String? myLocation; const MihBusinessProfilePreview({ super.key, required this.business, @@ -27,7 +27,7 @@ class _MihBusinessProfilePreviewState extends State { String calculateDistance() { double distanceInKm = MIHLocationAPI().getDistanceInMeaters( - widget.myLocation, widget.business.gps_location) / + widget.myLocation!, widget.business.gps_location) / 1000; return "${distanceInKm.toStringAsFixed(2)} km"; } @@ -80,7 +80,7 @@ class _MihBusinessProfilePreviewState extends State { ), ), Text( - calculateDistance(), + widget.myLocation != null ? calculateDistance() : "0.00 km", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, From a47f23c764c8d27b5674e1c395e0f891070fa796 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Wed, 9 Jul 2025 12:02:33 +0200 Subject: [PATCH 34/68] add user search to user service --- .../mih_business_user_search.dart | 32 +++++++++---------- .../lib/mih_services/mih_user_services.dart | 20 ++++++++++++ 2 files changed, 35 insertions(+), 17 deletions(-) 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 f55bb7d3..14abf077 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 @@ -1,16 +1,13 @@ -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_package_components/mih_search_bar.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; -import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:supertokens_flutter/http.dart' as http; +import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; class MihBusinessUserSearch extends StatefulWidget { final BusinessArguments arguments; @@ -33,18 +30,19 @@ class _MihBusinessUserSearchState extends State { String errorBody = ""; Future> fetchUsers(String search) async { - 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'); - } + 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() { @@ -142,7 +140,7 @@ class _MihBusinessUserSearchState extends State { } else { return Center( child: Text( - "$errorCode: Error pulling Patients Data\n/patients/search/$userSearch\n$errorBody", + "$errorCode: Error pulling Patients Data\n/users/search/$userSearch\n$errorBody", style: TextStyle( fontSize: 25, color: diff --git a/Frontend/lib/mih_services/mih_user_services.dart b/Frontend/lib/mih_services/mih_user_services.dart index 4c8f9551..01d1ebb4 100644 --- a/Frontend/lib/mih_services/mih_user_services.dart +++ b/Frontend/lib/mih_services/mih_user_services.dart @@ -63,6 +63,26 @@ class MihUserServices { } } + Future> searchUsers( + String searchText, + BuildContext context, + ) async { + var response = await http.get( + Uri.parse("${AppEnviroment.baseApiUrl}/users/search/$searchText"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + ); + 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 users'); + } + } + Future getUserDetails( String app_id, BuildContext context, From b9c9063571297603ef5dd5bf198b6896ca796731 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Wed, 9 Jul 2025 16:12:46 +0200 Subject: [PATCH 35/68] add business search api --- backend/routers/business.py | 40 ++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/backend/routers/business.py b/backend/routers/business.py index 97057d88..0dc993d0 100644 --- a/backend/routers/business.py +++ b/backend/routers/business.py @@ -61,6 +61,44 @@ class businessUpdateRequestV2(BaseModel): mission_vision: str +# Get List of all files +@router.get("/businesses/search/{search}", tags=["MIH Business"]) +async def read_all_businesses(search: str, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session()) + db = database.dbConnection.dbAppDataConnect() + cursor = db.cursor() + query = "SELECT business.business_id, business.Name, business.type, business.registration_no, " + query += "business.logo_name, business.logo_path, business.contact_no, business.bus_email, " + query += "business.gps_location, " + query += "practice_no, vat_no, " + query += "website, rating, mission_vision " + query += "FROM business " + query += "WHERE LOWER(business.Name) LIKE %s OR LOWER(business.type) LIKE %s" + search_term = f"%{search.lower()}%" # Add wildcards and lowercase + cursor.execute(query, (search_term, search_term)) + items = [ + { + "business_id": item[0], + "Name": item[1], + "type": item[2], + "registration_no": item[3], + "logo_name": item[4], + "logo_path": item[5], + "contact_no": item[6], + "bus_email": item[7], + "app_id": "", + "gps_location": item[8], + "practice_no": item[9], + "vat_no": item[10], + "website": item[11], + "rating": item[12], + "mission_vision": item[13], + } + for item in cursor.fetchall() + ] + cursor.close() + db.close() + return items + # Get List of all files @router.get("/business/business_id/{business_id}", tags=["MIH Business"]) async def read_business_by_business_id(business_id: str, session: SessionContainer = Depends(verify_session())): #, session: SessionContainer = Depends(verify_session()) @@ -69,7 +107,7 @@ async def read_business_by_business_id(business_id: str, session: SessionContain query = "SELECT business.business_id, business.Name, business.type, business.registration_no, " query += "business.logo_name, business.logo_path, business.contact_no, business.bus_email, " query += "business_users.app_id, business.gps_location, " - query += "practice_no, vat_no " + query += "practice_no, vat_no, " query += "website, rating, mission_vision " query += "FROM business " query += "inner join business_users " From dd78fab259feecc889fd616ad3cde2db2230668b Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Wed, 9 Jul 2025 16:13:08 +0200 Subject: [PATCH 36/68] I dont know --- .../mih_business_profile_preview.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart b/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart index eaea39a3..5c7359d0 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart @@ -63,7 +63,7 @@ class _MihBusinessProfilePreviewState extends State { ); } else { return Icon( - MihIcons.mihLogo, + MihIcons.iDontKnow, size: profilePictureWidth, ); } @@ -80,7 +80,9 @@ class _MihBusinessProfilePreviewState extends State { ), ), Text( - widget.myLocation != null ? calculateDistance() : "0.00 km", + widget.myLocation != null || widget.myLocation!.isEmpty + ? calculateDistance() + : "0.00 km", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 12, From a7a2577a4f7ef16d95dbb64d8d1e6c50e135e016 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Wed, 9 Jul 2025 16:13:41 +0200 Subject: [PATCH 37/68] search mzansi --- .../mih_personal_profile_preview.dart | 37 ++-- .../mih_loading_circle.dart | 28 ++- .../build_business_search_resultsList.dart | 44 +++++ .../build_user_search_results_list.dart | 41 ++++ .../mzansi_directory/mzansi_directory.dart | 10 +- .../package_tools/mih_search_mzansi.dart | 182 +++++++++++++++++- .../mih_business_details_services.dart | 20 ++ 7 files changed, 336 insertions(+), 26 deletions(-) create mode 100644 Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart create mode 100644 Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart diff --git a/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart b/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart index f8cb958f..cdc8850a 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart @@ -40,22 +40,33 @@ class _MihPersonalProfilePreviewState extends State { builder: (context, asyncSnapshot) { if (asyncSnapshot.connectionState == ConnectionState.done && asyncSnapshot.hasData) { - return MihCircleAvatar( - imageFile: NetworkImage(asyncSnapshot.requireData), - width: profilePictureWidth, - editable: false, - fileNameController: TextEditingController(), - userSelectedfile: file, - frameColor: - MzanziInnovationHub.of(context)!.theme.secondaryColor(), - backgroundColor: - MzanziInnovationHub.of(context)!.theme.primaryColor(), - onChange: () {}, - ); + if (asyncSnapshot.requireData != "") { + return MihCircleAvatar( + imageFile: NetworkImage(asyncSnapshot.requireData), + width: profilePictureWidth, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + backgroundColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.iDontKnow, + size: profilePictureWidth, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ); + } } else { return Icon( - MihIcons.mihLogo, + MihIcons.mihRing, size: profilePictureWidth, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), ); } }), diff --git a/Frontend/lib/mih_components/mih_pop_up_messages/mih_loading_circle.dart b/Frontend/lib/mih_components/mih_pop_up_messages/mih_loading_circle.dart index 8d61a660..22f1704d 100644 --- a/Frontend/lib/mih_components/mih_pop_up_messages/mih_loading_circle.dart +++ b/Frontend/lib/mih_components/mih_pop_up_messages/mih_loading_circle.dart @@ -3,7 +3,8 @@ import '../../main.dart'; import 'package:gif_view/gif_view.dart'; class Mihloadingcircle extends StatefulWidget { - const Mihloadingcircle({super.key}); + final String? message; + const Mihloadingcircle({super.key, this.message}); @override State createState() => _MihloadingcircleState(); @@ -53,7 +54,7 @@ class _MihloadingcircleState extends State { child: Container( padding: EdgeInsets.all(popUpPaddingSize), width: 250, - height: 250, + height: 275, decoration: BoxDecoration( color: MzanziInnovationHub.of(context)!.theme.primaryColor(), borderRadius: BorderRadius.circular(25.0), @@ -61,11 +62,24 @@ class _MihloadingcircleState extends State { color: MzanziInnovationHub.of(context)!.theme.primaryColor(), width: 5.0), ), - child: GifView.asset( - MzanziInnovationHub.of(context)!.theme.loadingImageLocation(), - height: 200, - width: 200, - frameRate: 30, + child: Column( + children: [ + GifView.asset( + MzanziInnovationHub.of(context)!.theme.loadingImageLocation(), + height: 200, + width: 200, + frameRate: 30, + ), + widget.message != null + ? Text( + widget.message!, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + ), + ) + : SizedBox(), + ], )), ); } diff --git a/Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart b/Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart new file mode 100644 index 00000000..60806ff0 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart'; + +class BuildBusinessSearchResultsList extends StatefulWidget { + final List businessList; + final String myLocation; + const BuildBusinessSearchResultsList({ + super.key, + required this.businessList, + required this.myLocation, + }); + + @override + State createState() => + _BuildBusinessSearchResultsListState(); +} + +class _BuildBusinessSearchResultsListState + extends State { + @override + Widget build(BuildContext context) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: widget.businessList.length, + separatorBuilder: (BuildContext context, index) { + return Divider( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ); + }, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 15.0), + child: MihBusinessProfilePreview( + business: widget.businessList[index], + myLocation: widget.myLocation, + ), + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart b/Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart new file mode 100644 index 00000000..acab3150 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart @@ -0,0 +1,41 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_personal_profile_preview.dart'; + +class BuildUserSearchResultsList extends StatefulWidget { + final List userList; + const BuildUserSearchResultsList({ + super.key, + required this.userList, + }); + + @override + State createState() => + _BuildUserSearchResultsListState(); +} + +class _BuildUserSearchResultsListState + extends State { + @override + Widget build(BuildContext context) { + return ListView.separated( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + itemCount: widget.userList.length, + separatorBuilder: (BuildContext context, index) { + return Divider( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ); + }, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 15.0), + child: MihPersonalProfilePreview( + user: widget.userList[index], + ), + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart index 3bdfc329..f872e271 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart @@ -34,9 +34,9 @@ class _MzansiDirectoryState extends State { List getToolBody() { List toolBodies = [ + MihSearchMzansi(), MihContacts(), MihFavouriteBusinesses(), - MihSearchMzansi(), ]; return toolBodies; } @@ -54,17 +54,17 @@ class _MzansiDirectoryState extends State { MihPackageTools getTools() { Map temp = {}; - temp[const Icon(Icons.person)] = () { + temp[const Icon(Icons.search)] = () { setState(() { _selcetedIndex = 0; }); }; - temp[const Icon(Icons.business_center)] = () { + temp[const Icon(Icons.person)] = () { setState(() { _selcetedIndex = 1; }); }; - temp[const Icon(Icons.search)] = () { + temp[const Icon(Icons.business_center)] = () { setState(() { _selcetedIndex = 2; }); @@ -77,9 +77,9 @@ class _MzansiDirectoryState extends State { List getToolTitle() { List toolTitles = [ + "Search Mzansi", "Contacts", "Favourite Businesses", - "Search Mzansi", ]; return toolTitles; } diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart index 24d18acc..b7cc477a 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart @@ -1,8 +1,17 @@ import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; class MihSearchMzansi extends StatefulWidget { const MihSearchMzansi({super.key}); @@ -14,6 +23,24 @@ class MihSearchMzansi extends StatefulWidget { class _MihSearchMzansiState extends State { final TextEditingController mzansiSearchController = TextEditingController(); final FocusNode searchFocusNode = FocusNode(); + bool userSearch = true; + Future?> futureUserSearchResults = Future.value(); + Future?> futureBusinessSearchResults = Future.value(); + late Future futurePosition = + MIHLocationAPI().getGPSPosition(context); + List userSearchResults = []; + List businessSearchResults = []; + + @override + void dispose() { + super.dispose(); + mzansiSearchController.dispose(); + } + + @override + void initState() { + super.initState(); + } @override Widget build(BuildContext context) { @@ -35,16 +62,169 @@ class _MihSearchMzansiState extends State { controller: mzansiSearchController, hintText: "Search Mzansi", prefixIcon: Icons.search, + suffixTools: [ + IconButton( + onPressed: () { + setState(() { + // searchTypeVisibility = !searchTypeVisibility; + userSearch = !userSearch; + }); + }, + icon: Icon( + Icons.display_settings, + size: 35, + color: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + )) + ], fillColor: MzanziInnovationHub.of(context)!.theme.secondaryColor(), hintColor: MzanziInnovationHub.of(context)!.theme.primaryColor(), - onPrefixIconTap: () {}, + onPrefixIconTap: () { + if (userSearch) { + setState(() { + futureUserSearchResults = MihUserServices() + .searchUsers(mzansiSearchController.text, context); + }); + } else { + setState(() { + futureBusinessSearchResults = MihBusinessDetailsServices() + .searchBusinesses(mzansiSearchController.text, context); + }); + } + }, + onClearIconTap: () { + setState(() { + futureUserSearchResults = Future.value(); + futureBusinessSearchResults = Future.value(); + mzansiSearchController.clear(); + }); + }, searchFocusNode: searchFocusNode, ), ), const SizedBox(height: 10), + FutureBuilder( + future: futurePosition, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == ConnectionState.waiting) { + return const Mihloadingcircle( + message: "Getting things ready for you", + ); + } else { + final myLocation = asyncSnapshot.data + .toString() + .replaceAll("Latitude: ", "") + .replaceAll("Longitude: ", ""); + print("My Location is : $myLocation"); + return displaySearchResults(userSearch, myLocation); + } + }), ], ), ); } + + Widget displaySearchResults(bool userSearch, String myLocation) { + if (userSearch) { + return FutureBuilder( + future: futureUserSearchResults, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Mihloadingcircle(); + } else if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData) { + // return Text("Pulled Data successfully"); + return BuildUserSearchResultsList(userList: snapshot.requireData!); + } else if (!snapshot.hasData) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon( + Icons.search, + size: 165, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + const SizedBox(height: 10), + Text( + "People Of Mzansi!", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ], + ); + } else { + return Center( + child: Text( + "Error pulling Patients Data\n/users/search/${mzansiSearchController.text}", + style: TextStyle( + fontSize: 25, + color: MzanziInnovationHub.of(context)!.theme.errorColor()), + textAlign: TextAlign.center, + ), + ); + } + }, + ); + } else { + return FutureBuilder( + future: futureBusinessSearchResults, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.waiting) { + return const Mihloadingcircle(); + } else if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData) { + // return Text("Pulled Data successfully"); + return BuildBusinessSearchResultsList( + businessList: snapshot.requireData!, + myLocation: myLocation, + ); + } else if (!snapshot.hasData) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Icon( + Icons.search, + size: 165, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + const SizedBox(height: 10), + Text( + "Businesses Of Mzansi!", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ], + ); + } else { + return Center( + child: Text( + "Error pulling Patients Data\n/users/search/${mzansiSearchController.text}", + style: TextStyle( + fontSize: 25, + color: MzanziInnovationHub.of(context)!.theme.errorColor()), + textAlign: TextAlign.center, + ), + ); + } + }, + ); + } + } } diff --git a/Frontend/lib/mih_services/mih_business_details_services.dart b/Frontend/lib/mih_services/mih_business_details_services.dart index aa469d5f..5049c148 100644 --- a/Frontend/lib/mih_services/mih_business_details_services.dart +++ b/Frontend/lib/mih_services/mih_business_details_services.dart @@ -9,6 +9,26 @@ import '../mih_components/mih_pop_up_messages/mih_error_message.dart'; import 'package:supertokens_flutter/http.dart' as http; class MihBusinessDetailsServices { + Future> searchBusinesses( + String searchText, + BuildContext context, + ) async { + var response = await http.get( + Uri.parse("${AppEnviroment.baseApiUrl}/businesses/search/$searchText"), + headers: { + "Content-Type": "application/json; charset=UTF-8" + }, + ); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List businesses = + List.from(l.map((model) => Business.fromJson(model))); + return businesses; + } else { + throw Exception('failed to load users'); + } + } + Future getBusinessDetails( String app_id, ) async { From 7682fbd108a8dd1572e6f4afd1940e56412a13c1 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 10:13:12 +0200 Subject: [PATCH 38/68] Add Mzansi Directory to MIH Home --- .../mih_home/package_tools/mih_business_home.dart | 13 ++++++++++--- .../mih_home/package_tools/mih_personal_home.dart | 8 ++++---- 2 files changed, 14 insertions(+), 7 deletions(-) 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 2da37769..602b381a 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 @@ -12,6 +12,7 @@ import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tile/about_ import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tiles/mih_calculator_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/calendar/package_tiles/mzansi_calendar_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tiles/mzansi_ai_tile.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_setup_business_profile_tile.dart'; import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/package_tiles/pat_manager_tile.dart'; @@ -112,10 +113,9 @@ class _MihBusinessHomeState extends State packageSize: packageSize, ) }); - //=============== Mzansi AI =============== + //=============== Mzansi Directory =============== temp.add({ - "Mzansi AI": MzansiAiTile( - signedInUser: widget.signedInUser, + "Mzansi Directory": MzansiDirectoryTile( packageSize: packageSize, ) }); @@ -126,6 +126,13 @@ class _MihBusinessHomeState extends State packageSize: packageSize, ) }); + //=============== Mzansi AI =============== + temp.add({ + "Mzansi AI": MzansiAiTile( + signedInUser: widget.signedInUser, + packageSize: packageSize, + ) + }); //=============== About MIH =============== temp.add({"About MIH": AboutMihTile(packageSize: packageSize)}); return temp; diff --git a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart index e1747155..29087ac5 100644 --- a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart +++ b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart @@ -114,10 +114,9 @@ class _MihPersonalHomeState extends State packageSize: packageSize, ) }); - //=============== Mzansi AI =============== + //=============== Mzansi Directory =============== temp.add({ - "Mzansi AI": MzansiAiTile( - signedInUser: widget.signedInUser, + "Mzansi Directory": MzansiDirectoryTile( packageSize: packageSize, ) }); @@ -135,7 +134,8 @@ class _MihPersonalHomeState extends State }); //=============== Mzansi AI =============== temp.add({ - "Mzansi Directory": MzansiDirectoryTile( + "Mzansi AI": MzansiAiTile( + signedInUser: widget.signedInUser, packageSize: packageSize, ) }); From ecfa28c28755a4c869b01205205d6465c2432ea4 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 10:13:38 +0200 Subject: [PATCH 39/68] Use Idont know icon for no picture --- .../mih_circle_avatar.dart | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) 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 25c0cee5..a5c5d130 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 @@ -36,15 +36,16 @@ class _MihCircleAvatarState extends State { ImageProvider? getAvatar() { Color dark = const Color(0XFF3A4454); if (widget.imageFile == null) { - if (widget.backgroundColor == dark) { - print("here in light icon"); - return const AssetImage( - 'lib/mih_components/mih_package_components/assets/images/i-dont-know-light.png'); - } else { - print("here in dark icon"); - return const AssetImage( - 'lib/mih_components/mih_package_components/assets/images/i-dont-know-dark.png'); - } + return null; + // if (widget.backgroundColor == dark) { + // print("here in light icon"); + // return const AssetImage( + // 'lib/mih_components/mih_package_components/assets/images/i-dont-know-light.png'); + // } else { + // print("here in dark icon"); + // return const AssetImage( + // 'lib/mih_components/mih_package_components/assets/images/i-dont-know-dark.png'); + // } } else { return widget.imageFile; } @@ -69,16 +70,30 @@ class _MihCircleAvatarState extends State { child: Stack( alignment: Alignment.center, children: [ - CircleAvatar( - radius: widget.width / 2.2, - backgroundColor: widget.backgroundColor, - backgroundImage: imagePreview, + Visibility( + visible: imagePreview != null, + child: CircleAvatar( + radius: widget.width / 2.2, + backgroundColor: widget.backgroundColor, + backgroundImage: imagePreview, + ), ), - FittedBox( - fit: BoxFit.fill, + Visibility( + visible: imagePreview != null, + child: FittedBox( + fit: BoxFit.fill, + child: Icon( + size: widget.width, + MihIcons.mihRing, + color: widget.frameColor, + ), + ), + ), + Visibility( + visible: imagePreview == null, child: Icon( + MihIcons.iDontKnow, size: widget.width, - MihIcons.mihRing, color: widget.frameColor, ), ), From 46ab131ce995f7a9dd2a632f0dc2d4aed2344332 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 10:16:09 +0200 Subject: [PATCH 40/68] remove unused var --- .../mih_package_components/mih_circle_avatar.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 a5c5d130..d076c49b 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 @@ -34,7 +34,7 @@ class _MihCircleAvatarState extends State { late ImageProvider? imagePreview; ImageProvider? getAvatar() { - Color dark = const Color(0XFF3A4454); + // Color dark = const Color(0XFF3A4454); if (widget.imageFile == null) { return null; // if (widget.backgroundColor == dark) { From ab8b722e5e7a719898ecd412deb0a681566c358c Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 10:16:52 +0200 Subject: [PATCH 41/68] Align business preview to personal preview --- .../mih_business_profile_preview.dart | 44 +++++++++++++------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart b/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart index 5c7359d0..8cba8112 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_business_profile_preview.dart @@ -49,21 +49,30 @@ class _MihBusinessProfilePreviewState extends State { builder: (context, asyncSnapshot) { if (asyncSnapshot.connectionState == ConnectionState.done && asyncSnapshot.hasData) { - return MihCircleAvatar( - imageFile: NetworkImage(asyncSnapshot.requireData), - width: profilePictureWidth, - editable: false, - fileNameController: TextEditingController(), - userSelectedfile: file, - frameColor: - MzanziInnovationHub.of(context)!.theme.secondaryColor(), - backgroundColor: - MzanziInnovationHub.of(context)!.theme.primaryColor(), - onChange: () {}, - ); + if (asyncSnapshot.requireData != "") { + return MihCircleAvatar( + imageFile: NetworkImage(asyncSnapshot.requireData), + width: profilePictureWidth, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + backgroundColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.iDontKnow, + size: profilePictureWidth, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ); + } } else { return Icon( - MihIcons.iDontKnow, + MihIcons.mihRing, size: profilePictureWidth, ); } @@ -79,13 +88,20 @@ class _MihBusinessProfilePreviewState extends State { fontSize: 18, ), ), + Text( + widget.business.type, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 15, + ), + ), Text( widget.myLocation != null || widget.myLocation!.isEmpty ? calculateDistance() : "0.00 km", style: TextStyle( fontWeight: FontWeight.bold, - fontSize: 12, + fontSize: 10, ), ), ], From c2f064de748a6e454575fa70efca29b03319661b Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 10:17:16 +0200 Subject: [PATCH 42/68] fix error with test package --- .../package_tools/package_tool_one.dart | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart index 2872da06..2770ba9f 100644 --- a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart +++ b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart @@ -227,19 +227,19 @@ class _PackageToolOneState extends State { // print(asyncSnapshot.connectionState); if (asyncSnapshot.connectionState == ConnectionState.waiting) { - return MihBusinessProfilePreview( - business: widget.business, - myLocation: null, - ).redacted( - context: context, - redact: true, - ); - // return Container( - // width: 150, - // height: 50, - // // color: Colors.black, - // child: Center(child: CircularProgressIndicator()), + // return MihBusinessProfilePreview( + // business: widget.business, + // myLocation: null, + // ).redacted( + // context: context, + // redact: true, // ); + return Container( + width: 150, + height: 50, + // color: Colors.black, + child: Center(child: CircularProgressIndicator()), + ); } else if (asyncSnapshot.hasError || !asyncSnapshot.hasData || asyncSnapshot.data == null) { From 61ebd75963aee559974d9589ab77f692ac36dff1 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 10:17:56 +0200 Subject: [PATCH 43/68] remove unused import --- .../Example/package_tools/package_tool_one.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart index 2770ba9f..4d2a120c 100644 --- a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart +++ b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart @@ -29,7 +29,6 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_time_field.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_toggle.dart'; -import 'package:redacted/redacted.dart'; class PackageToolOne extends StatefulWidget { final AppUser user; From 11784a07ae304a2805af72510b3a21cb72e39d2e Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 10:18:21 +0200 Subject: [PATCH 44/68] add display for new user --- .../package_tools/mih_personal_profile.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 df1b6575..61404c32 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 @@ -468,7 +468,9 @@ class _MihPersonalProfileState extends State { ), FittedBox( child: Text( - widget.arguments.signedInUser.username, + widget.arguments.signedInUser.username.isNotEmpty + ? widget.arguments.signedInUser.username + : "username", style: TextStyle( fontSize: 35, fontWeight: FontWeight.bold, @@ -480,7 +482,9 @@ class _MihPersonalProfileState extends State { ), FittedBox( child: Text( - "${widget.arguments.signedInUser.fname} ${widget.arguments.signedInUser.lname}", + widget.arguments.signedInUser.fname.isNotEmpty + ? "${widget.arguments.signedInUser.fname} ${widget.arguments.signedInUser.lname}" + : "Name Surname", style: TextStyle( fontSize: 25, fontWeight: FontWeight.bold, From 2f30b2b64eaa5292728b984ea58e763827aceefb Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 10:18:50 +0200 Subject: [PATCH 45/68] update icon for personal --- .../mzansi_profile/personal_profile/mzansi_profile.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart index 667c061b..c9c201f1 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart @@ -49,7 +49,7 @@ class _MzansiProfileState extends State { MihPackageTools getTools() { Map temp = {}; - temp[const Icon(Icons.perm_identity)] = () { + temp[const Icon(Icons.person)] = () { setState(() { _selcetedIndex = 0; }); From a8a0f3d6207a2fff8226151d352f23cf22fa3d30 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 10:25:36 +0200 Subject: [PATCH 46/68] fix practice number requirement --- .../package_tools/mih_business_details.dart | 33 +++++--- .../profile_business_add.dart | 77 +++++++++++-------- 2 files changed, 69 insertions(+), 41 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart index 10795ed2..5cb83d05 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart @@ -13,7 +13,6 @@ import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; -import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_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_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; @@ -270,17 +269,32 @@ class _MihBusinessDetailsState extends State { }, ), const SizedBox(height: 10), - MihDropdownField( + MihTextFormField( + fillColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + inputColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), controller: typeController, + multiLineInput: false, + requiredText: true, hintText: "Business Type", - dropdownOptions: const ["Doctors Office", "Other"], - editable: true, - enableSearch: true, validator: (value) { return MihValidationServices().isEmpty(value); }, - requiredText: true, ), + // MihDropdownField( + // controller: typeController, + // hintText: "Business Type", + // dropdownOptions: const ["Doctors Office", "Other"], + // editable: true, + // enableSearch: true, + // validator: (value) { + // return MihValidationServices().isEmpty(value); + // }, + // requiredText: true, + // ), const SizedBox(height: 10), MihTextFormField( fillColor: MzanziInnovationHub.of(context)! @@ -409,8 +423,7 @@ class _MihBusinessDetailsState extends State { typeController.text == "Doctors Office", hintText: "Practice Number", validator: (validateValue) { - return MihValidationServices() - .isEmpty(validateValue); + return null; }, ), const SizedBox(height: 10), @@ -453,7 +466,9 @@ class _MihBusinessDetailsState extends State { showDialog( context: context, builder: (context) { - return const Mihloadingcircle(); + return const Mihloadingcircle( + message: "Getting your location", + ); }, ); MIHLocationAPI() diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart index ce072c29..7d20fd8c 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/profile_business_add.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:http/http.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_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'; @@ -230,7 +231,7 @@ class _ProfileBusinessAddState extends State { headerAlignment: MainAxisAlignment.center, headerItems: [ Text( - "Add Business Profile", + "Set Up Business Profile", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 25, @@ -304,17 +305,32 @@ class _ProfileBusinessAddState extends State { }, ), const SizedBox(height: 10.0), - MihDropdownField( + MihTextFormField( + fillColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + inputColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), controller: typeController, + multiLineInput: false, + requiredText: true, hintText: "Business Type", - dropdownOptions: const ["Doctors Office", "Other"], - editable: true, - enableSearch: true, validator: (value) { return MihValidationServices().isEmpty(value); }, - requiredText: true, ), + // MihDropdownField( + // controller: typeController, + // hintText: "Business Type", + // dropdownOptions: const ["Doctors Office", "Other"], + // editable: true, + // enableSearch: true, + // validator: (value) { + // return MihValidationServices().isEmpty(value); + // }, + // requiredText: true, + // ), const SizedBox(height: 10.0), MihTextFormField( fillColor: MzanziInnovationHub.of(context)! @@ -430,34 +446,22 @@ class _ProfileBusinessAddState extends State { }, ), const SizedBox(height: 10.0), - ValueListenableBuilder( - valueListenable: busType, - builder: (BuildContext context, String value, - Widget? child) { - return Visibility( - visible: value == "Doctors Office", - child: MihTextFormField( - fillColor: MzanziInnovationHub.of(context)! - .theme - .secondaryColor(), - inputColor: MzanziInnovationHub.of(context)! - .theme - .primaryColor(), - controller: practiceNoController, - multiLineInput: false, - requiredText: true, - hintText: "Practice Number", - validator: (validateValue) { - if (value == "Doctors Office") { - return MihValidationServices() - .isEmpty(validateValue); - } - return null; - }, - ), - ); + MihTextFormField( + fillColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + inputColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + controller: practiceNoController, + multiLineInput: false, + requiredText: false, + hintText: "Practice Number", + validator: (validateValue) { + return null; }, ), + const SizedBox(height: 10.0), MihTextFormField( fillColor: MzanziInnovationHub.of(context)! @@ -495,6 +499,14 @@ class _ProfileBusinessAddState extends State { const SizedBox(width: 10.0), MihButton( onPressed: () { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle( + message: "Getting your location", + ); + }, + ); MIHLocationAPI() .getGPSPosition(context) .then((position) { @@ -504,6 +516,7 @@ class _ProfileBusinessAddState extends State { "${position.latitude}, ${position.longitude}"; }); } + Navigator.of(context).pop(); }); }, buttonColor: MzanziInnovationHub.of(context)! From 364f0302a97cb0f16032554138b69095204c2d7b Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 10:27:05 +0200 Subject: [PATCH 47/68] fix error when no profile picture --- Frontend/lib/mih_services/mih_business_details_services.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Frontend/lib/mih_services/mih_business_details_services.dart b/Frontend/lib/mih_services/mih_business_details_services.dart index 5049c148..7e5f0cf1 100644 --- a/Frontend/lib/mih_services/mih_business_details_services.dart +++ b/Frontend/lib/mih_services/mih_business_details_services.dart @@ -69,6 +69,9 @@ 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: { @@ -79,7 +82,7 @@ class MihBusinessDetailsServices { "type": businessType, "registration_no": businessRegistrationNo, "logo_name": businessLogoFilename, - "logo_path": "$appId/business_files/$businessLogoFilename", + "logo_path": logoPath, "contact_no": businessPhoneNumber, "bus_email": businessEmail, "gps_location": businessLocation, From 2b8ca4ef50273dfe9649194eefe7b4d08477144b Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 11:17:05 +0200 Subject: [PATCH 48/68] Add Mzansi Preview Route --- Frontend/lib/mih_config/mih_routeGenerator.dart | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Frontend/lib/mih_config/mih_routeGenerator.dart b/Frontend/lib/mih_config/mih_routeGenerator.dart index b7b36736..d457542c 100644 --- a/Frontend/lib/mih_config/mih_routeGenerator.dart +++ b/Frontend/lib/mih_config/mih_routeGenerator.dart @@ -19,6 +19,7 @@ import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/mzansi_direc 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/profile_business_add.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:mzansi_innovation_hub/mih_packages/mzansi_wallet/components/mih_barcode_scanner.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/mih_wallet.dart'; import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/pat_manager.dart'; @@ -45,6 +46,7 @@ class AppRoutes { static const String forgotPassword = '/forgot-password'; static const String aboutMih = '/about'; static const String mzansiProfile = '/mzansi-profile'; + static const String mzansiProfileView = '/mzansi-profile/view'; static const String businessProfileSetup = '/business-profile/set-up'; static const String businessProfileManage = '/business-profile/manage'; static const String patientProfile = '/patient-profile'; @@ -54,8 +56,7 @@ class AppRoutes { static const String mzansiDirectory = '/mzansi-directory'; static const String mihAccess = '/mih-access'; static const String calendar = '/calendar'; - static const String appointments = - '/appointments'; // Consider unifying with /calendar + static const String appointments = '/appointments'; static const String patientManager = '/patient-manager'; static const String patientManagerPatient = '/patient-manager/patient'; static const String fileViewer = '/file-veiwer'; @@ -156,6 +157,15 @@ class RouteGenerator { } break; + case AppRoutes.mzansiProfileView: + if (args is AppUser) { + return MaterialPageRoute( + settings: settings, + builder: (_) => MzansiProfileView(user: args), + ); + } + break; + case AppRoutes.businessProfileSetup: if (args is AppUser) { return MaterialPageRoute( From 5d4c36626b743415f75e15f9fc6b172a58c58683 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 11:17:23 +0200 Subject: [PATCH 49/68] add defualt text --- .../mih_personal_profile_preview.dart | 62 ++++++++++--------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart b/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart index cdc8850a..8e7ee029 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_personal_profile_preview.dart @@ -36,53 +36,57 @@ class _MihPersonalProfilePreviewState extends State { return Row( children: [ FutureBuilder( - future: futureImageUrl, - builder: (context, asyncSnapshot) { - if (asyncSnapshot.connectionState == ConnectionState.done && - asyncSnapshot.hasData) { - if (asyncSnapshot.requireData != "") { - return MihCircleAvatar( - imageFile: NetworkImage(asyncSnapshot.requireData), - width: profilePictureWidth, - editable: false, - fileNameController: TextEditingController(), - userSelectedfile: file, - frameColor: - MzanziInnovationHub.of(context)!.theme.secondaryColor(), - backgroundColor: - MzanziInnovationHub.of(context)!.theme.primaryColor(), - onChange: () {}, - ); - } else { - return Icon( - MihIcons.iDontKnow, - size: profilePictureWidth, - color: - MzanziInnovationHub.of(context)!.theme.secondaryColor(), - ); - } + future: futureImageUrl, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == ConnectionState.done && + asyncSnapshot.hasData) { + if (asyncSnapshot.requireData != "") { + return MihCircleAvatar( + imageFile: NetworkImage(asyncSnapshot.requireData), + width: profilePictureWidth, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + backgroundColor: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + onChange: () {}, + ); } else { return Icon( - MihIcons.mihRing, + MihIcons.iDontKnow, size: profilePictureWidth, color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), ); } - }), + } else { + return Icon( + MihIcons.mihRing, + size: profilePictureWidth, + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ); + } + }, + ), const SizedBox(width: 15), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - widget.user.username, + widget.user.username.isNotEmpty + ? widget.user.username + : "Username", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 18, ), ), Text( - "${widget.user.fname} ${widget.user.lname}", + widget.user.fname.isNotEmpty + ? "${widget.user.fname} ${widget.user.lname}" + : "Name Surname", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 15, From bfb175aa601e188935279096fbaf8fc97e365a84 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 11:17:35 +0200 Subject: [PATCH 50/68] add defualt text --- .../build_user_search_results_list.dart | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart b/Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart index acab3150..84f7d84c 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart @@ -29,10 +29,29 @@ class _BuildUserSearchResultsListState ); }, itemBuilder: (context, index) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 15.0), - child: MihPersonalProfilePreview( - user: widget.userList[index], + return Material( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + child: InkWell( + onTap: () { + Navigator.of(context).pushNamed( + '/mzansi-profile/view', + arguments: widget.userList[index], + ); + }, + splashColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor() + .withOpacity(0.2), + borderRadius: BorderRadius.circular(15), + child: Padding( + padding: EdgeInsetsGeometry.symmetric( + // vertical: 5, + horizontal: 25, + ), + child: MihPersonalProfilePreview( + user: widget.userList[index], + ), + ), ), ); }, From c582ead2f5456d8c77d5a3544abe2f9ac0d808b1 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 11:17:48 +0200 Subject: [PATCH 51/68] remove padding --- .../components/mih_business_card.dart | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart index 5c531b57..9ba16202 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart @@ -264,6 +264,7 @@ class _MihBusinessCardState extends State { borderRadius: BorderRadius.circular(15), child: Padding( padding: EdgeInsetsGeometry.symmetric( + // vertical: 5, horizontal: 25, ), child: Row( @@ -338,11 +339,8 @@ class _MihBusinessCardState extends State { _makePhoneCall(widget.cellNumber); }, ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Divider( - color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - ), + Divider( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), ), _buildContactInfo( "Email", @@ -358,11 +356,8 @@ class _MihBusinessCardState extends State { ); }, ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Divider( - color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - ), + Divider( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), ), _buildContactInfo( "Location", @@ -380,11 +375,8 @@ class _MihBusinessCardState extends State { ), Visibility( visible: widget.website != null && widget.website! != "", - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), - child: Divider( - color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - ), + child: Divider( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), ), ), Visibility( From 4f8c69caf3ed1d0c774a5e4cac14d68b4ff80e9b Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 11:17:59 +0200 Subject: [PATCH 52/68] add profile preview package --- .../personal_profile/mzansi_profile_view.dart | 76 +++++++ .../mih_personal_profile_view.dart | 198 ++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart create mode 100644 Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile_view.dart diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart new file mode 100644 index 00000000..a1c47ae8 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart @@ -0,0 +1,76 @@ +import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.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_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile_view.dart'; +import 'package:flutter/material.dart'; + +class MzansiProfileView extends StatefulWidget { + final AppUser user; + const MzansiProfileView({ + super.key, + required this.user, + }); + + @override + State createState() => _MzansiProfileViewState(); +} + +class _MzansiProfileViewState extends State { + int _selcetedIndex = 0; + + @override + Widget build(BuildContext context) { + return MihPackage( + appActionButton: getAction(), + appTools: getTools(), + appBody: getToolBody(), + appToolTitles: getToolTitle(), + selectedbodyIndex: _selcetedIndex, + onIndexChange: (newValue) { + setState(() { + _selcetedIndex = newValue; + }); + }, + ); + } + + MihPackageAction getAction() { + return MihPackageAction( + icon: const Icon(Icons.arrow_back), + iconSize: 35, + onTap: () { + Navigator.of(context).pop(); + FocusScope.of(context).unfocus(); + }, + ); + } + + MihPackageTools getTools() { + Map temp = {}; + temp[const Icon(Icons.person)] = () { + setState(() { + _selcetedIndex = 0; + }); + }; + return MihPackageTools( + tools: temp, + selcetedIndex: _selcetedIndex, + ); + } + + List getToolBody() { + List toolBodies = []; + toolBodies.add(MihPersonalProfileView( + user: widget.user, + )); + return toolBodies; + } + + List getToolTitle() { + List toolTitles = [ + "Profile", + ]; + return toolTitles; + } +} diff --git a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile_view.dart b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile_view.dart new file mode 100644 index 00000000..8f0822f5 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile_view.dart @@ -0,0 +1,198 @@ +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; + +class MihPersonalProfileView extends StatefulWidget { + final AppUser user; + const MihPersonalProfileView({ + super.key, + required this.user, + }); + + @override + State createState() => _MihPersonalProfileViewState(); +} + +class _MihPersonalProfileViewState extends State { + late Future futureImageUrl; + PlatformFile? file; + + @override + void dispose() { + super.dispose(); + } + + @override + void initState() { + super.initState(); + futureImageUrl = + MihFileApi.getMinioFileUrl(widget.user.pro_pic_path, context); + } + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return MihPackageToolBody( + borderOn: false, + innerHorizontalPadding: 10, + bodyItem: getBody(screenWidth), + ); + } + + Widget getBody(double width) { + double profilePictureWidth = 150; + return MihSingleChildScroll( + child: Padding( + padding: MzanziInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: width * 0.2) + : EdgeInsets.symmetric(horizontal: width * 0.075), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + FutureBuilder( + future: futureImageUrl, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == ConnectionState.done && + asyncSnapshot.hasData) { + if (asyncSnapshot.requireData != "") { + return MihCircleAvatar( + imageFile: NetworkImage(asyncSnapshot.requireData), + width: profilePictureWidth, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + backgroundColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.iDontKnow, + size: profilePictureWidth, + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + ); + } + } else { + return Icon( + MihIcons.mihRing, + size: profilePictureWidth, + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + ); + } + // return Center( + // child: MihCircleAvatar( + // imageFile: propicPreview, + // width: 150, + // editable: false, + // fileNameController: proPicController, + // userSelectedfile: proPic, + // frameColor: MzanziInnovationHub.of(context)! + // .theme + // .secondaryColor(), + // backgroundColor: + // MzanziInnovationHub.of(context)!.theme.primaryColor(), + // onChange: (selectedImage) { + // setState(() { + // proPic = selectedImage; + // }); + // }, + // ), + // ); + }), + FittedBox( + child: Text( + widget.user.username.isNotEmpty + ? widget.user.username + : "Username", + style: TextStyle( + fontSize: 35, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ), + FittedBox( + child: Text( + widget.user.fname.isNotEmpty + ? "${widget.user.fname} ${widget.user.lname}" + : "Name Surname", + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ), + FittedBox( + child: Text( + widget.user.type.toUpperCase(), + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ), + const SizedBox(height: 10.0), + Center( + child: SizedBox( + width: 700, + child: Text( + widget.user.purpose.isNotEmpty + ? widget.user.purpose + : "No purpose added yet", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ), + ), + const SizedBox(height: 30.0), + // Center( + // child: MihButton( + // onPressed: () { + // // Connect with the user + // }, + // buttonColor: + // MzanziInnovationHub.of(context)!.theme.successColor(), + // width: 300, + // child: Text( + // widget.user.username.isEmpty + // ? "Set Up Profile" + // : "Edit Profile", + // style: TextStyle( + // color: + // MzanziInnovationHub.of(context)!.theme.primaryColor(), + // fontSize: 20, + // fontWeight: FontWeight.bold, + // ), + // ), + // ), + // ), + ], + ), + ), + ); + } +} From 771c5c546f8205478491e60a0b38b968bd74200c Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 11:28:05 +0200 Subject: [PATCH 53/68] Sort Users A-Z --- .../mzansi_directory/package_tools/mih_search_mzansi.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart index b7cc477a..42217e55 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart @@ -135,6 +135,8 @@ class _MihSearchMzansiState extends State { } else if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) { // return Text("Pulled Data successfully"); + snapshot.requireData! + .sort((a, b) => a.username.compareTo(b.username)); return BuildUserSearchResultsList(userList: snapshot.requireData!); } else if (!snapshot.hasData) { return Column( From f4260cc81b03ad376922f6d6a4c0bb6f59182f4a Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 11:59:11 +0200 Subject: [PATCH 54/68] Sort businesses --- .../package_tools/mih_search_mzansi.dart | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart index 42217e55..12de39ff 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart @@ -68,6 +68,15 @@ class _MihSearchMzansiState extends State { setState(() { // searchTypeVisibility = !searchTypeVisibility; userSearch = !userSearch; + if (userSearch) { + futureUserSearchResults = MihUserServices() + .searchUsers( + mzansiSearchController.text, context); + } else { + futureBusinessSearchResults = + MihBusinessDetailsServices().searchBusinesses( + mzansiSearchController.text, context); + } }); }, icon: Icon( @@ -137,7 +146,16 @@ class _MihSearchMzansiState extends State { // return Text("Pulled Data successfully"); snapshot.requireData! .sort((a, b) => a.username.compareTo(b.username)); - return BuildUserSearchResultsList(userList: snapshot.requireData!); + return Column( + children: [ + Text( + "People of Mzansi", + style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + BuildUserSearchResultsList(userList: snapshot.requireData!), + ], + ); } else if (!snapshot.hasData) { return Column( mainAxisAlignment: MainAxisAlignment.center, @@ -185,9 +203,19 @@ class _MihSearchMzansiState extends State { } else if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) { // return Text("Pulled Data successfully"); - return BuildBusinessSearchResultsList( - businessList: snapshot.requireData!, - myLocation: myLocation, + snapshot.requireData!.sort((a, b) => a.Name.compareTo(b.Name)); + return Column( + children: [ + Text( + "Businesses of Mzansi", + style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 10), + BuildBusinessSearchResultsList( + businessList: snapshot.requireData!, + myLocation: myLocation, + ), + ], ); } else if (!snapshot.hasData) { return Column( From acafbf0d398afd3eaf5bef12b1f9f17a2b86deef Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 13:00:12 +0200 Subject: [PATCH 55/68] add business view route --- Frontend/lib/mih_config/mih_routeGenerator.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Frontend/lib/mih_config/mih_routeGenerator.dart b/Frontend/lib/mih_config/mih_routeGenerator.dart index d457542c..130a1c98 100644 --- a/Frontend/lib/mih_config/mih_routeGenerator.dart +++ b/Frontend/lib/mih_config/mih_routeGenerator.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_print_prevew.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/Example/package_test.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_notification_message.dart'; import 'package:mzansi_innovation_hub/mih_packages/about_mih/about_mih.dart'; @@ -17,6 +18,7 @@ import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/mih_authen 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/personal_profile/mzansi_profile.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart'; @@ -49,6 +51,7 @@ class AppRoutes { static const String mzansiProfileView = '/mzansi-profile/view'; static const String businessProfileSetup = '/business-profile/set-up'; static const String businessProfileManage = '/business-profile/manage'; + static const String businessProfileView = '/business-profile/view'; static const String patientProfile = '/patient-profile'; static const String patientProfileSetup = '/patient-profile/set-up'; static const String patientProfileEdit = '/patient-profile/edit'; @@ -184,6 +187,15 @@ class RouteGenerator { } break; + case AppRoutes.businessProfileView: + if (args is Business) { + return MaterialPageRoute( + settings: settings, + builder: (_) => MzansiBusinessProfileView(business: args), + ); + } + break; + case AppRoutes.patientProfile: if (args is PatientViewArguments) { return MaterialPageRoute( From ccec5bf097f46fbc5ece9ffaceaf151f077c1bfc Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 13:00:42 +0200 Subject: [PATCH 56/68] add navigation on click --- .../build_business_search_resultsList.dart | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart b/Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart index 60806ff0..39b69ca0 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart @@ -31,11 +31,30 @@ class _BuildBusinessSearchResultsListState ); }, itemBuilder: (context, index) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 15.0), - child: MihBusinessProfilePreview( - business: widget.businessList[index], - myLocation: widget.myLocation, + return Material( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + child: InkWell( + onTap: () { + Navigator.of(context).pushNamed( + '/business-profile/view', + arguments: widget.businessList[index], + ); + }, + splashColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor() + .withOpacity(0.2), + borderRadius: BorderRadius.circular(15), + child: Padding( + padding: EdgeInsetsGeometry.symmetric( + // vertical: 5, + horizontal: 25, + ), + child: MihBusinessProfilePreview( + business: widget.businessList[index], + myLocation: widget.myLocation, + ), + ), ), ); }, From e08032d7f4e3cddbf8354bcfe3427244c5bfa803 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 13:00:56 +0200 Subject: [PATCH 57/68] business profile view --- .../mzansi_business_profile_view.dart | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart new file mode 100644 index 00000000..f70aaefd --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart @@ -0,0 +1,76 @@ +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart'; + +class MzansiBusinessProfileView extends StatefulWidget { + final Business business; + const MzansiBusinessProfileView({ + super.key, + required this.business, + }); + + @override + State createState() => + _MzansiBusinessProfileViewState(); +} + +class _MzansiBusinessProfileViewState extends State { + int _selcetedIndex = 0; + + @override + Widget build(BuildContext context) { + return MihPackage( + appActionButton: getAction(), + appTools: getTools(), + appBody: getToolBody(), + appToolTitles: getToolTitle(), + selectedbodyIndex: _selcetedIndex, + onIndexChange: (newValue) { + setState(() { + _selcetedIndex = newValue; + }); + }, + ); + } + + MihPackageAction getAction() { + return MihPackageAction( + icon: const Icon(Icons.arrow_back), + iconSize: 35, + onTap: () { + Navigator.of(context).pop(); + FocusScope.of(context).unfocus(); + }, + ); + } + + MihPackageTools getTools() { + Map temp = {}; + temp[const Icon(Icons.business)] = () { + setState(() { + _selcetedIndex = 0; + }); + }; + return MihPackageTools( + tools: temp, + selcetedIndex: _selcetedIndex, + ); + } + + List getToolBody() { + List toolBodies = [ + MihBusinessDetailsView(business: widget.business), + ]; + return toolBodies; + } + + List getToolTitle() { + List toolTitles = [ + "Profile", + ]; + return toolTitles; + } +} From 960388bfd01f17ffcc98197cd7e0c604fb8d788a Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 13:01:04 +0200 Subject: [PATCH 58/68] personal profile view --- .../mih_business_details_view.dart | 180 ++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart new file mode 100644 index 00000000..2d2a7f75 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart @@ -0,0 +1,180 @@ +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; + +class MihBusinessDetailsView extends StatefulWidget { + final Business business; + const MihBusinessDetailsView({ + super.key, + required this.business, + }); + + @override + State createState() => _MihBusinessDetailsViewState(); +} + +class _MihBusinessDetailsViewState extends State { + late Future futureImageUrl; + PlatformFile? file; + + @override + void dispose() { + super.dispose(); + } + + @override + void initState() { + super.initState(); + futureImageUrl = + MihFileApi.getMinioFileUrl(widget.business.logo_path, context); + } + + @override + Widget build(BuildContext context) { + double screenWidth = MediaQuery.of(context).size.width; + return MihPackageToolBody( + borderOn: false, + innerHorizontalPadding: 10, + bodyItem: getBody(screenWidth, context), + ); + } + + Widget getBody(double width, BuildContext context) { + double profilePictureWidth = 150; + return Stack( + children: [ + MihSingleChildScroll( + child: Padding( + padding: + MzanziInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: width * 0.2) + : EdgeInsets.symmetric(horizontal: width * 0.075), + child: Column( + children: [ + FutureBuilder( + future: futureImageUrl, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == + ConnectionState.done && + asyncSnapshot.hasData) { + if (asyncSnapshot.requireData != "") { + return MihCircleAvatar( + imageFile: NetworkImage(asyncSnapshot.requireData), + width: profilePictureWidth, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + backgroundColor: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.iDontKnow, + size: profilePictureWidth, + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + ); + } + } else { + return Icon( + MihIcons.mihRing, + size: profilePictureWidth, + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + ); + } + }), + // Center( + // child: MihCircleAvatar( + // imageFile: widget.logoImage, + // width: 150, + // editable: false, + // fileNameController: fileNameController, + // userSelectedfile: imageFile, + // frameColor: + // MzanziInnovationHub.of(context)!.theme.secondaryColor(), + // backgroundColor: + // MzanziInnovationHub.of(context)!.theme.primaryColor(), + // onChange: (selectedfile) { + // setState(() { + // imageFile = selectedfile; + // }); + // }, + // ), + // ), + FittedBox( + child: Text( + widget.business.Name, + style: TextStyle( + fontSize: 35, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + ), + ), + ), + // FittedBox( + // child: Text( + // "Mission & Vision", + // style: TextStyle( + // fontSize: 15, + // fontWeight: FontWeight.bold, + // color: MzanziInnovationHub.of(context)! + // .theme + // .secondaryColor(), + // ), + // ), + // ), + Center( + child: SizedBox( + width: 700, + child: Text( + widget.business.mission_vision.isNotEmpty + ? widget.business.mission_vision + : "No Mission & Vision added yet", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.bold, + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor(), + ), + ), + ), + ), + const SizedBox(height: 20), + SizedBox( + width: 700, + child: MihBusinessCard( + businessName: widget.business.Name, + cellNumber: widget.business.contact_no, + email: widget.business.bus_email, + gpsLocation: widget.business.gps_location, + //To-Do: Add the business Website + website: widget.business.website, + ), + ), + ], + ), + ), + ), + ], + ); + } +} From b244378a1de85f8b0a156396df545845d928c15b Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 13:01:18 +0200 Subject: [PATCH 59/68] add mzansi directory package index --- .../lib/mih_packages/mzansi_directory/mzansi_directory.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart index f872e271..a5370cfc 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart @@ -77,7 +77,7 @@ class _MzansiDirectoryState extends State { List getToolTitle() { List toolTitles = [ - "Search Mzansi", + "Mzansi Search", "Contacts", "Favourite Businesses", ]; From 82e3126b0e3e09f3a9f82d6b14bd483534b73f58 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 13:18:35 +0200 Subject: [PATCH 60/68] comment out other tools --- .../mzansi_directory/mzansi_directory.dart | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart index a5370cfc..17332452 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/mzansi_directory.dart @@ -59,16 +59,16 @@ class _MzansiDirectoryState extends State { _selcetedIndex = 0; }); }; - temp[const Icon(Icons.person)] = () { - setState(() { - _selcetedIndex = 1; - }); - }; - temp[const Icon(Icons.business_center)] = () { - setState(() { - _selcetedIndex = 2; - }); - }; + // temp[const Icon(Icons.person)] = () { + // setState(() { + // _selcetedIndex = 1; + // }); + // }; + // temp[const Icon(Icons.business_center)] = () { + // setState(() { + // _selcetedIndex = 2; + // }); + // }; return MihPackageTools( tools: temp, selcetedIndex: _selcetedIndex, From 7ca6467b9aaf0c5a6bc8ee7c7c04a99c3b7c1cdd Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 13:18:51 +0200 Subject: [PATCH 61/68] change Icon and position --- .../package_tools/mih_search_mzansi.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart index 12de39ff..efb9ba74 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart @@ -3,6 +3,7 @@ import 'package:geolocator/geolocator.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; @@ -118,7 +119,7 @@ class _MihSearchMzansiState extends State { builder: (context, asyncSnapshot) { if (asyncSnapshot.connectionState == ConnectionState.waiting) { return const Mihloadingcircle( - message: "Getting things ready for you", + message: "Getting Your GPS Location Ready", ); } else { final myLocation = asyncSnapshot.data @@ -161,8 +162,9 @@ class _MihSearchMzansiState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ + const SizedBox(height: 50), Icon( - Icons.search, + MihIcons.personalProfile, size: 165, color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), @@ -222,8 +224,9 @@ class _MihSearchMzansiState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ + const SizedBox(height: 50), Icon( - Icons.search, + MihIcons.businessProfile, size: 165, color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), From 19c0177956dc94971a52c2b0b0632b05ba8cf7a1 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 13:20:04 +0200 Subject: [PATCH 62/68] add spacer to ask mzansi home --- .../mih_packages/mih_home/package_tools/mih_business_home.dart | 1 + .../mih_packages/mih_home/package_tools/mih_personal_home.dart | 1 + 2 files changed, 2 insertions(+) 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 602b381a..5b1efdf5 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 @@ -285,6 +285,7 @@ class _MihBusinessHomeState extends State mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ + const SizedBox(height: 50), Icon( MihIcons.mzansiAi, size: 165, diff --git a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart index 29087ac5..a9818458 100644 --- a/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart +++ b/Frontend/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart @@ -331,6 +331,7 @@ class _MihPersonalHomeState extends State mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ + const SizedBox(height: 50), Icon( MihIcons.mzansiAi, size: 165, From 294481c11a9726644ccb2d9de1ecdbf94e47810f Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 13:31:06 +0200 Subject: [PATCH 63/68] no items display --- .../package_tools/mih_search_mzansi.dart | 63 ++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart index efb9ba74..b0f93e33 100644 --- a/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart +++ b/Frontend/lib/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart @@ -63,6 +63,9 @@ class _MihSearchMzansiState extends State { controller: mzansiSearchController, hintText: "Search Mzansi", prefixIcon: Icons.search, + prefixAltIcon: userSearch + ? MihIcons.personalProfile + : MihIcons.businessProfile, suffixTools: [ IconButton( onPressed: () { @@ -143,7 +146,8 @@ class _MihSearchMzansiState extends State { if (snapshot.connectionState == ConnectionState.waiting) { return const Mihloadingcircle(); } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { + snapshot.hasData && + snapshot.requireData!.isNotEmpty) { // return Text("Pulled Data successfully"); snapshot.requireData! .sort((a, b) => a.username.compareTo(b.username)); @@ -183,6 +187,33 @@ class _MihSearchMzansiState extends State { ), ], ); + } else if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData && + snapshot.requireData!.isEmpty) { + // return Text("Pulled Data successfully"); + return Column( + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.iDontKnow, + size: 165, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + const SizedBox(height: 10), + Text( + "Let's Try Refining Your Search", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ], + ); } else { return Center( child: Text( @@ -203,7 +234,8 @@ class _MihSearchMzansiState extends State { if (snapshot.connectionState == ConnectionState.waiting) { return const Mihloadingcircle(); } else if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { + snapshot.hasData && + snapshot.requireData!.isNotEmpty) { // return Text("Pulled Data successfully"); snapshot.requireData!.sort((a, b) => a.Name.compareTo(b.Name)); return Column( @@ -219,6 +251,33 @@ class _MihSearchMzansiState extends State { ), ], ); + } else if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData && + snapshot.requireData!.isEmpty) { + // return Text("Pulled Data successfully"); + return Column( + children: [ + const SizedBox(height: 50), + Icon( + MihIcons.iDontKnow, + size: 165, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + const SizedBox(height: 10), + Text( + "Let's Try Refining Your Search", + textAlign: TextAlign.center, + overflow: TextOverflow.visible, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + ), + ), + ], + ); } else if (!snapshot.hasData) { return Column( mainAxisAlignment: MainAxisAlignment.center, From e1009a8112c31eba318cfa8910c0f21a3830a4c0 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 13:44:49 +0200 Subject: [PATCH 64/68] Fix profile set up --- .../lib/mih_components/mih_package_components/mih_icons.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Frontend/lib/mih_components/mih_package_components/mih_icons.dart b/Frontend/lib/mih_components/mih_package_components/mih_icons.dart index 6d6ddde9..bfd4a9ac 100644 --- a/Frontend/lib/mih_components/mih_package_components/mih_icons.dart +++ b/Frontend/lib/mih_components/mih_package_components/mih_icons.dart @@ -54,7 +54,7 @@ class MihIcons { IconData(0xe90d, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); static const IconData profileSetup = - IconData(0xe90d, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); + IconData(0xe90e, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); static const IconData calculator = IconData(0xe940, fontFamily: _mihFontFam, fontPackage: _mihFontPkg); From 8ae1d938291a766fcb86047887d1d9980a56f4be Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 13:44:59 +0200 Subject: [PATCH 65/68] add attributions --- Frontend/lib/mih_packages/about_mih/about_mih.dart | 2 +- .../about_mih/package_tools/mih_ attributes.dart | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Frontend/lib/mih_packages/about_mih/about_mih.dart b/Frontend/lib/mih_packages/about_mih/about_mih.dart index e71da5d1..0115df4c 100644 --- a/Frontend/lib/mih_packages/about_mih/about_mih.dart +++ b/Frontend/lib/mih_packages/about_mih/about_mih.dart @@ -100,7 +100,7 @@ class _AboutMihState extends State { "About", "Privacy Policy", "Terms of Service", - "Attributes", + "Attributions", ]; return toolTitles; } diff --git a/Frontend/lib/mih_packages/about_mih/package_tools/mih_ attributes.dart b/Frontend/lib/mih_packages/about_mih/package_tools/mih_ attributes.dart index aac1860d..b96de189 100644 --- a/Frontend/lib/mih_packages/about_mih/package_tools/mih_ attributes.dart +++ b/Frontend/lib/mih_packages/about_mih/package_tools/mih_ attributes.dart @@ -99,11 +99,11 @@ class _MihAttributesState extends State { Widget getBody() { String message = - "Some APIs, Icons and Assets used in this MIH were sourced from third party providers.\n"; + "Some APIs, Icons and Assets used in MIH were sourced from third party providers.\n"; message += "We are grateful to the talented creators for providing these resources.\n"; message += - "As per the terms for free user for these third party providers, the following assets require attribution"; + "As per the terms for free use for these third party providers, the following assets require attribution"; return MihSingleChildScroll( child: Column( @@ -184,10 +184,11 @@ class _MihAttributesState extends State { ), ], ), - displayIcon(MihIcons.mihLogo, "Tarah Meth", - "https://www.linkedin.com/in/tarah-meth-3b6309254/"), displayIcon(MihIcons.mihRing, "Tarah Meth", "https://www.linkedin.com/in/tarah-meth-3b6309254/"), + displayIcon(MihIcons.mihLogo, "Tarah Meth", + "https://www.linkedin.com/in/tarah-meth-3b6309254/"), + displayIcon(MihIcons.mzansiAi, "Ollama", "https://ollama.com/"), displayIcon(MihIcons.mzansiWallet, "Freepik", "https://www.flaticon.com/free-icon/wallet-passes-app_3884407?term=wallet&page=1&position=21&origin=search&related_id=3884407"), displayIcon(MihIcons.patientProfile, "RaftelDesign", @@ -200,6 +201,8 @@ class _MihAttributesState extends State { "https://www.flaticon.com/free-icon/calculator_2374409?term=calculator&page=1&position=20&origin=search&related_id=2374409"), displayIcon(MihIcons.aboutMih, "Chanut", "https://www.flaticon.com/free-icon/info_151776?term=about&page=1&position=8&origin=search&related_id=151776"), + displayIcon(MihIcons.personalProfile, "Freepik", + "https://www.flaticon.com/free-icon/user_1077063?term=profile&page=1&position=6&origin=search&related_id=1077063"), displayIcon(MihIcons.businessProfile, "Gravisio", "https://www.flaticon.com/free-icon/contractor_11813336?term=company+profile&page=1&position=2&origin=search&related_id=11813336"), displayIcon(MihIcons.patientManager, "Vector Tank", @@ -210,6 +213,8 @@ class _MihAttributesState extends State { "https://www.flaticon.com/free-icon/business_13569850?term=company+add&page=1&position=25&origin=search&related_id=13569850"), displayIcon(MihIcons.calculator, "fawazahmed0", "https://github.com/fawazahmed0/exchange-api"), + displayIcon(MihIcons.iDontKnow, "Freepik", + "https://www.flaticon.com/free-icon/i-dont-know_5359909?term=i+dont+know&page=1&position=7&origin=search&related_id=5359909"), ], ), ), From 3ab099a53a2335c7dea5a8f0cea493d843622edf Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 14:00:35 +0200 Subject: [PATCH 66/68] chnage business card to business infop card --- .../Example/package_tools/package_tool_one.dart | 2 +- .../{mih_business_card.dart => mih_business_info_card.dart} | 0 .../business_profile/package_tools/mih_business_details.dart | 2 +- .../package_tools/mih_business_details_view.dart | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename Frontend/lib/mih_packages/mzansi_profile/business_profile/components/{mih_business_card.dart => mih_business_info_card.dart} (100%) diff --git a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart index 4d2a120c..fb8be284 100644 --- a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart +++ b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart @@ -8,7 +8,7 @@ import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_banner_ad.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_personal_profile_preview.dart'; -import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart similarity index 100% rename from Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart rename to Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart index 5cb83d05..3ef2a88c 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart @@ -5,7 +5,7 @@ import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.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_business_card.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart index 2d2a7f75..a7558b4e 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; -import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_card.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; From 35e10752ef65daa92f68bad0ed7e83fc27179cb3 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 20:01:42 +0200 Subject: [PATCH 67/68] Fixed loading indicator with message --- .../package_tools/package_tool_one.dart | 30 +++++++++ .../mih_loading_circle.dart | 65 +++++++++++-------- 2 files changed, 67 insertions(+), 28 deletions(-) diff --git a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart index fb8be284..9b5c6c8f 100644 --- a/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart +++ b/Frontend/lib/mih_components/mih_package_components/Example/package_tools/package_tool_one.dart @@ -8,6 +8,7 @@ import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_banner_ad.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_personal_profile_preview.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_business_info_card.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart'; @@ -182,6 +183,35 @@ class _PackageToolOneState extends State { ], ), const SizedBox(height: 20), + Center( + child: MihButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return const Mihloadingcircle( + message: "Getting your profile data", + ); + }, + ); + }, + buttonColor: + MzanziInnovationHub.of(context)!.theme.secondaryColor(), + elevation: 10, + width: 300, + child: Text( + "Show Loading", + style: TextStyle( + color: MzanziInnovationHub.of(context)! + .theme + .primaryColor(), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ), + const SizedBox(height: 10), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ diff --git a/Frontend/lib/mih_components/mih_pop_up_messages/mih_loading_circle.dart b/Frontend/lib/mih_components/mih_pop_up_messages/mih_loading_circle.dart index 22f1704d..98206878 100644 --- a/Frontend/lib/mih_components/mih_pop_up_messages/mih_loading_circle.dart +++ b/Frontend/lib/mih_components/mih_pop_up_messages/mih_loading_circle.dart @@ -51,36 +51,45 @@ class _MihloadingcircleState extends State { @override Widget build(BuildContext context) { return Dialog( - child: Container( - padding: EdgeInsets.all(popUpPaddingSize), - width: 250, - height: 275, - decoration: BoxDecoration( - color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - borderRadius: BorderRadius.circular(25.0), - border: Border.all( + child: IntrinsicWidth( + child: IntrinsicHeight( + child: Container( + padding: EdgeInsets.all(popUpPaddingSize), + // width: 250, + // height: 275, + decoration: BoxDecoration( color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - width: 5.0), - ), - child: Column( - children: [ - GifView.asset( - MzanziInnovationHub.of(context)!.theme.loadingImageLocation(), - height: 200, - width: 200, - frameRate: 30, + borderRadius: BorderRadius.circular(25.0), + border: Border.all( + color: + MzanziInnovationHub.of(context)!.theme.primaryColor(), + width: 5.0), ), - widget.message != null - ? Text( - widget.message!, - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.bold, - ), - ) - : SizedBox(), - ], - )), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + GifView.asset( + MzanziInnovationHub.of(context)! + .theme + .loadingImageLocation(), + height: 200, + width: 200, + frameRate: 30, + ), + widget.message != null + ? Text( + widget.message!, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ) + : SizedBox(), + ], + )), + ), + ), ); } } From 5c906ef29fe72de65f170002d55cd71fe21633d8 Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Thu, 10 Jul 2025 20:08:49 +0200 Subject: [PATCH 68/68] add elevatio to business info card --- .../components/mih_business_info_card.dart | 224 +++++++++--------- 1 file changed, 117 insertions(+), 107 deletions(-) diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart index 9ba16202..02bf1290 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart @@ -321,116 +321,126 @@ class _MihBusinessCardState extends State { @override Widget build(BuildContext context) { - return Container( - decoration: BoxDecoration( - color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), - borderRadius: BorderRadius.circular(10), - ), - child: Column( - children: [ - const SizedBox(height: 10), - _buildContactInfo( - "Call", - "Give us a quick call.", - Icons.phone, - const Color(0xffaff0b3), - () { - // print("Calling ${widget.cellNumber}"); - _makePhoneCall(widget.cellNumber); - }, - ), - Divider( - color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - ), - _buildContactInfo( - "Email", - "Send us an email.", - Icons.email, - const Color(0xffdaa2e9), - () { - // print("Emailing ${widget.email}"); - _launchEmail( - widget.email, - "Inquiery about ${widget.businessName}", - "Dear ${widget.businessName},\n\nI would like to inquire about your services.\n\nBest regards,\n", - ); - }, - ), - Divider( - color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - ), - _buildContactInfo( - "Location", - "Come visit us.", - Icons.location_on, - const Color(0xffe9e8a1), - () { - final latitude = double.parse(widget.gpsLocation.split(',')[0]); - final longitude = double.parse(widget.gpsLocation.split(',')[1]); - _launchGoogleMapsWithUrl( - latitude: latitude, - longitude: longitude, - ); - }, - ), - Visibility( - visible: widget.website != null && widget.website! != "", - child: Divider( - color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - ), - ), - Visibility( - visible: widget.website != null && widget.website! != "", - child: _buildContactInfo( - "Website", - "Find out more about us.", - Icons.vpn_lock, - const Color(0xffd67d8a), + return Material( + color: MzanziInnovationHub.of(context)! + .theme + .secondaryColor() + .withValues(alpha: 0.6), + borderRadius: BorderRadius.circular(25), + elevation: 10, + shadowColor: Colors.black, + child: Container( + decoration: BoxDecoration( + color: MzanziInnovationHub.of(context)!.theme.secondaryColor(), + borderRadius: BorderRadius.circular(10), + ), + child: Column( + children: [ + const SizedBox(height: 10), + _buildContactInfo( + "Call", + "Give us a quick call.", + Icons.phone, + const Color(0xffaff0b3), () { - _launchWebsite(widget.website!); + // print("Calling ${widget.cellNumber}"); + _makePhoneCall(widget.cellNumber); }, ), - ), - // Padding( - // padding: const EdgeInsets.symmetric(horizontal: 10.0), - // child: Divider( - // color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - // ), - // ), - // _buildContactInfo( - // "Rate Us", - // "Let us know how we are doing.", - // Icons.star_rate_rounded, - // const Color(0xffd69d7d), - // () { - // print("Opeining rating dialog"); - // // _launchWebsite(widget.website); - // }, - // ), - // Padding( - // padding: const EdgeInsets.symmetric(horizontal: 10.0), - // child: Divider( - // color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - // ), - // ), - // _buildContactInfo( - // "Bookmark", - // "Save us for later.", - // Icons.bookmark_add_rounded, - // const Color(0xff6e7dcc), - // () { - // // _launchWebsite(widget.website); - // print("Saving ${widget.businessName} to Directory"); - // }, - // ), - const SizedBox(height: 10), - // Padding( - // padding: const EdgeInsets.symmetric(horizontal: 10.0), - // child: Divider( - // color: MzanziInnovationHub.of(context)!.theme.primaryColor(), - // ), - // ), - ], + Divider( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + _buildContactInfo( + "Email", + "Send us an email.", + Icons.email, + const Color(0xffdaa2e9), + () { + // print("Emailing ${widget.email}"); + _launchEmail( + widget.email, + "Inquiery about ${widget.businessName}", + "Dear ${widget.businessName},\n\nI would like to inquire about your services.\n\nBest regards,\n", + ); + }, + ), + Divider( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + _buildContactInfo( + "Location", + "Come visit us.", + Icons.location_on, + const Color(0xffe9e8a1), + () { + final latitude = double.parse(widget.gpsLocation.split(',')[0]); + final longitude = + double.parse(widget.gpsLocation.split(',')[1]); + _launchGoogleMapsWithUrl( + latitude: latitude, + longitude: longitude, + ); + }, + ), + Visibility( + visible: widget.website != null && widget.website! != "", + child: Divider( + color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + ), + ), + Visibility( + visible: widget.website != null && widget.website! != "", + child: _buildContactInfo( + "Website", + "Find out more about us.", + Icons.vpn_lock, + const Color(0xffd67d8a), + () { + _launchWebsite(widget.website!); + }, + ), + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 10.0), + // child: Divider( + // color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + // ), + // ), + // _buildContactInfo( + // "Rate Us", + // "Let us know how we are doing.", + // Icons.star_rate_rounded, + // const Color(0xffd69d7d), + // () { + // print("Opeining rating dialog"); + // // _launchWebsite(widget.website); + // }, + // ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 10.0), + // child: Divider( + // color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + // ), + // ), + // _buildContactInfo( + // "Bookmark", + // "Save us for later.", + // Icons.bookmark_add_rounded, + // const Color(0xff6e7dcc), + // () { + // // _launchWebsite(widget.website); + // print("Saving ${widget.businessName} to Directory"); + // }, + // ), + const SizedBox(height: 10), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 10.0), + // child: Divider( + // color: MzanziInnovationHub.of(context)!.theme.primaryColor(), + // ), + // ), + ], + ), ), ); }