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 1b75e44d..124bb903 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 @@ -1,8 +1,11 @@ import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_review.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_add_bookmark_alert.dart'; @@ -31,6 +34,14 @@ class MihBusinessCard extends StatefulWidget { class _MihBusinessCardState extends State { Future? _businessReviewFuture; Future? _bookmarkedBusinessFuture; + bool _isUserSignedIn = false; + + Future _checkUserSession() async { + final doesSessionExist = await SuperTokens.doesSessionExist(); + setState(() { + _isUserSignedIn = doesSessionExist; + }); + } RedactedConfiguration getRedactedConfiguration() { return RedactedConfiguration( @@ -390,6 +401,7 @@ class _MihBusinessCardState extends State { @override void initState() { super.initState(); + _checkUserSession(); _businessReviewFuture = getUserReview(); _bookmarkedBusinessFuture = getUserBookmark(); } @@ -665,33 +677,103 @@ class _MihBusinessCardState extends State { Future businessReviewRatingWindow( BusinessReview? myReview, bool previouslyRated, double width) async { - showDialog( - context: context, - builder: (context) => MihReviewBusinessWindow( - business: widget.business, - businessReview: myReview, - screenWidth: width, - readOnly: false, - ), - ); + if (_isUserSignedIn) { + showDialog( + context: context, + builder: (context) => MihReviewBusinessWindow( + business: widget.business, + businessReview: myReview, + screenWidth: width, + readOnly: false, + ), + ); + } else { + showSignInRequiredAlert(); + } } void showAddBookmarkAlert() { - showDialog( - context: context, - builder: (context) => MihAddBookmarkAlert( - business: widget.business, - ), - ); + if (_isUserSignedIn) { + showDialog( + context: context, + builder: (context) => MihAddBookmarkAlert( + business: widget.business, + ), + ); + } else { + showSignInRequiredAlert(); + } } void showDeleteBookmarkAlert(BookmarkedBusiness? bookmarkBusiness) { + if (_isUserSignedIn) { + showDialog( + context: context, + builder: (context) => MihDeleteBookmarkAlert( + business: widget.business, + bookmarkBusiness: bookmarkBusiness, + startUpSearch: widget.startUpSearch, + )); + } else { + showSignInRequiredAlert(); + } + } + + void showSignInRequiredAlert() { showDialog( - context: context, - builder: (context) => MihDeleteBookmarkAlert( - business: widget.business, - bookmarkBusiness: bookmarkBusiness, - startUpSearch: widget.startUpSearch, - )); + context: context, + builder: (context) => MihPackageAlert( + alertIcon: Column( + children: [ + Icon( + MihIcons.mihLogo, + size: 125, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + const SizedBox(height: 10), + ], + ), + alertTitle: "Let's Get Started", + alertBody: Column( + children: [ + Text( + "Ready to dive in to the world of MIH?\nSign in or create a free MIH account to unlock all the powerful features of the MIH app. It's quick and easy!", + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + context.goNamed( + 'mihHome', + extra: true, + ); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Sign In/ Create Account", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ); } } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart index 60eea3b3..f106ec95 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart @@ -1,4 +1,5 @@ import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; @@ -108,6 +109,11 @@ class _MzansiBusinessProfileState extends State { _selcetedIndex = 4; }); }; + temp[const Icon(Icons.qr_code_rounded)] = () { + setState(() { + _selcetedIndex = 5; + }); + }; return MihPackageTools( tools: temp, selcetedIndex: _selcetedIndex, @@ -160,6 +166,10 @@ class _MzansiBusinessProfileState extends State { MihMyBusinessTeam(arguments: widget.arguments), MihBusinessUserSearch(arguments: widget.arguments), MihBusinessReviews(business: widget.arguments.business!), + MihBusinessQrCode( + business: widget.arguments.business!, + startUpSearch: "", + ), ]; return toolBodies; } @@ -169,8 +179,9 @@ class _MzansiBusinessProfileState extends State { "Profile", "User", "Team", - "Add Member", + "Add", "Reviews", + "Share", ]; return toolTitles; } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart index d8b14250..2e625382 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart @@ -1,17 +1,24 @@ import 'package:go_router/go_router.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart'; import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; class MzansiBusinessProfileView extends StatefulWidget { - final BusinessViewArguments arguments; + final BusinessViewArguments? arguments; + final String? businessId; const MzansiBusinessProfileView({ super.key, required this.arguments, + required this.businessId, }); @override @@ -21,21 +28,62 @@ class MzansiBusinessProfileView extends StatefulWidget { class _MzansiBusinessProfileViewState extends State { int _selcetedIndex = 0; + Business? business; + String startUpSearch = ""; + + Future _fetchBusinessDetails() async { + if (widget.arguments != null) { + setState(() { + business = widget.arguments!.business; + startUpSearch = widget.arguments!.startUpSearch ?? ""; + }); + } else if (widget.businessId != null) { + final biz = await MihBusinessDetailsServices() + .getBusinessDetailsByBusinessId(widget.businessId!); + if (biz == null) { + context.goNamed( + 'mihHome', + extra: true, + ); + } else { + KenLogger.success("Business found: ${biz.Name}"); + setState(() { + business = biz; + startUpSearch = ""; + }); + } + } + } + + @override + void initState() { + super.initState(); + _fetchBusinessDetails(); + } @override Widget build(BuildContext context) { - return MihPackage( - appActionButton: getAction(), - appTools: getTools(), - appBody: getToolBody(), - appToolTitles: getToolTitle(), - selectedbodyIndex: _selcetedIndex, - onIndexChange: (newValue) { - setState(() { - _selcetedIndex = newValue; - }); - }, - ); + if (business == null) { + KenLogger.warning("Business is null, showing loading indicator"); + return Scaffold( + body: const Center( + child: Mihloadingcircle(), + ), + ); + } else { + return MihPackage( + appActionButton: getAction(), + appTools: getTools(), + appBody: getToolBody(), + appToolTitles: getToolTitle(), + selectedbodyIndex: _selcetedIndex, + onIndexChange: (newValue) { + setState(() { + _selcetedIndex = newValue; + }); + }, + ); + } } MihPackageAction getAction() { @@ -47,7 +95,7 @@ class _MzansiBusinessProfileViewState extends State { "mzansiDirectory", extra: MzansiDirectoryArguments( personalSearch: false, - startSearchText: widget.arguments.business.Name, + startSearchText: business!.Name, ), ); FocusScope.of(context).unfocus(); @@ -67,6 +115,11 @@ class _MzansiBusinessProfileViewState extends State { _selcetedIndex = 1; }); }; + temp[const Icon(Icons.qr_code_rounded)] = () { + setState(() { + _selcetedIndex = 2; + }); + }; return MihPackageTools( tools: temp, selcetedIndex: _selcetedIndex, @@ -76,10 +129,14 @@ class _MzansiBusinessProfileViewState extends State { List getToolBody() { List toolBodies = [ MihBusinessDetailsView( - business: widget.arguments.business, - startUpSearch: widget.arguments.startUpSearch, + business: business!, + startUpSearch: startUpSearch, ), - MihBusinessReviews(business: widget.arguments.business), + MihBusinessReviews(business: business!), + MihBusinessQrCode( + business: business!, + startUpSearch: startUpSearch, + ) ]; return toolBodies; } @@ -88,6 +145,7 @@ class _MzansiBusinessProfileViewState extends State { List toolTitles = [ "Profile", "Reviews", + "Share Business", ]; return toolTitles; } diff --git a/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart new file mode 100644 index 00000000..463edd57 --- /dev/null +++ b/Frontend/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart @@ -0,0 +1,349 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_speed_dial/flutter_speed_dial.dart'; +import 'package:go_router/go_router.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_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_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart'; +import 'package:supertokens_flutter/supertokens.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class MihBusinessQrCode extends StatefulWidget { + final Business business; + final String? startUpSearch; + const MihBusinessQrCode({ + super.key, + required this.business, + required this.startUpSearch, + }); + + @override + State createState() => _MihBusinessQrCodeState(); +} + +class _MihBusinessQrCodeState extends State { + late Future futureImageUrl; + PlatformFile? file; + String qrCodedata = + "${AppEnviroment.baseAppUrl}/business-profile/view?business_id="; + int qrSize = 500; + bool _isUserSignedIn = false; + + Future _checkUserSession() async { + final doesSessionExist = await SuperTokens.doesSessionExist(); + setState(() { + _isUserSignedIn = doesSessionExist; + }); + } + + String getQrCodeData(int qrSize) { + String color = MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark") + .toARGB32() + .toRadixString(16) + .substring(2, 8); + // KenLogger.warning(color); + String bgColor = MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark") + .toARGB32() + .toRadixString(16) + .substring(2, 8); + // KenLogger.warning(bgColor); + String encodedData = + Uri.encodeComponent("$qrCodedata${widget.business.business_id}"); + + return "https://api.qrserver.com/v1/create-qr-code/?data=$encodedData&size=${qrSize}x${qrSize}&bgcolor=$bgColor&color=$color"; + } + + Future downloadQrCode() async { + if (_isUserSignedIn) { + final Uri uri = Uri.parse(getQrCodeData(1024)); + if (!await launchUrl(uri)) { + throw 'Could not launch $uri'; + } + } else { + showSignInRequiredAlert(); + } + } + + void showSignInRequiredAlert() { + showDialog( + context: context, + builder: (context) => MihPackageAlert( + alertIcon: Column( + children: [ + Icon( + MihIcons.mihLogo, + size: 125, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + const SizedBox(height: 10), + ], + ), + alertTitle: "Let's Get Started", + alertBody: Column( + children: [ + Text( + "Ready to dive in to the world of MIH?\nSign in or create a free MIH account to unlock all the powerful features of the MIH app. It's quick and easy!", + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 15, + ), + ), + const SizedBox(height: 25), + Center( + child: MihButton( + onPressed: () { + context.goNamed( + 'mihHome', + extra: true, + ); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + elevation: 10, + width: 300, + child: Text( + "Sign In/ Create Account", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ), + ) + ], + ), + alertColour: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ); + } + + @override + void dispose() { + super.dispose(); + } + + @override + void initState() { + super.initState(); + _checkUserSession(); + futureImageUrl = + MihFileApi.getMinioFileUrl(widget.business.logo_path, context); + } + + @override + Widget build(BuildContext context) { + Size screenSize = MediaQuery.of(context).size; + return MihPackageToolBody( + borderOn: false, + innerHorizontalPadding: 10, + bodyItem: getBody(screenSize, context), + ); + } + + Widget getBody(Size screenSize, BuildContext context) { + double profilePictureWidth = 150; + return SizedBox( + height: screenSize.height, + child: Stack( + alignment: Alignment.topCenter, + children: [ + MihSingleChildScroll( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 15.0), + child: Padding( + padding: MzansiInnovationHub.of(context)!.theme.screenType == + "desktop" + ? EdgeInsets.symmetric(horizontal: screenSize.width * 0.2) + : EdgeInsets.symmetric( + horizontal: screenSize.width * 0), //.075), + child: Padding( + padding: const EdgeInsets.only(top: 10.0), + child: Material( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark") + .withValues(alpha: 0.6), + borderRadius: BorderRadius.circular(25), + elevation: 10, + shadowColor: Colors.black, + child: Container( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + borderRadius: BorderRadius.circular(20), + ), + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + FutureBuilder( + future: futureImageUrl, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == + ConnectionState.done && + asyncSnapshot.hasData) { + if (asyncSnapshot.requireData != "") { + return MihCircleAvatar( + imageFile: NetworkImage( + asyncSnapshot.requireData), + width: profilePictureWidth, + editable: false, + fileNameController: + TextEditingController(), + userSelectedfile: file, + frameColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + backgroundColor: + MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.iDontKnow, + size: profilePictureWidth, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ); + } + } else { + return Icon( + MihIcons.mihRing, + size: profilePictureWidth, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ); + } + }, + ), + FittedBox( + child: Text( + widget.business.Name, + style: TextStyle( + fontSize: 35, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ), + FittedBox( + child: Text( + widget.business.type, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ), + const SizedBox(height: 10), + SizedBox( + width: 300, + height: 300, + child: CachedNetworkImage( + imageUrl: getQrCodeData(qrSize.toInt()), + placeholder: (context, url) => + const Mihloadingcircle(), + errorWidget: (context, url, error) => + const Icon(Icons.error), + ), + ), + const SizedBox(height: 10), + FittedBox( + child: Text( + "Scan & Connect", + style: TextStyle( + fontSize: 30, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)! + .theme + .mode == + "Dark"), + ), + ), + ), + ], + )), + ), + ), + ), + ), + ), + ), + Positioned( + right: 10, + bottom: 10, + child: MihFloatingMenu( + animatedIcon: AnimatedIcons.menu_close, + children: [ + SpeedDialChild( + child: Icon( + Icons.download_rounded, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + label: "Download QR Code", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onTap: () { + downloadQrCode(); + }, + ) + ]), + ) + ], + ), + ); + } +}