diff --git a/Frontend/lib/mih_objects/profile_link.dart b/Frontend/lib/mih_objects/profile_link.dart new file mode 100644 index 00000000..103a1e72 --- /dev/null +++ b/Frontend/lib/mih_objects/profile_link.dart @@ -0,0 +1,35 @@ +class ProfileLink { + final int idprofile_links; + final String app_id; + final String business_id; + final String destination; + final String web_link; + + const ProfileLink({ + required this.idprofile_links, + required this.app_id, + required this.business_id, + required this.destination, + required this.web_link, + }); + + factory ProfileLink.fromJson(Map json) { + return ProfileLink( + idprofile_links: json['idprofile_links'], + app_id: json['app_id'], + business_id: json['business_id'], + destination: json['destination'], + web_link: json['web_link'], + ); + } + + Map toJson() { + return { + 'idprofile_links': idprofile_links, + 'app_id': app_id, + 'business_id': business_id, + 'destination': destination, + 'web_link': web_link, + }; + } +} diff --git a/Frontend/lib/mih_package_components/Example/package_tiles/test_package_tile.dart b/Frontend/lib/mih_package_components/Example/package_tiles/test_package_tile.dart index 565f3c32..a3c2ca54 100644 --- a/Frontend/lib/mih_package_components/Example/package_tiles/test_package_tile.dart +++ b/Frontend/lib/mih_package_components/Example/package_tiles/test_package_tile.dart @@ -38,9 +38,7 @@ class _TestPackageTileState extends State { MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), iconSize: widget.packageSize, - primaryColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - secondaryColor: MihColors.getPrimaryColor( + textColor: MihColors.getSecondaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ); } diff --git a/Frontend/lib/mih_package_components/Example/package_tools/package_tool_three.dart b/Frontend/lib/mih_package_components/Example/package_tools/package_tool_three.dart new file mode 100644 index 00000000..1682426a --- /dev/null +++ b/Frontend/lib/mih_package_components/Example/package_tools/package_tool_three.dart @@ -0,0 +1,127 @@ +import 'package:flutter/material.dart'; +import 'package:mzansi_innovation_hub/mih_objects/profile_link.dart'; +import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_package_components/mih_profile_links.dart'; +import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart'; + +class PackageToolThree extends StatefulWidget { + const PackageToolThree({super.key}); + + @override + State createState() => _PackageToolThreeState(); +} + +class _PackageToolThreeState extends State { + @override + Widget build(BuildContext context) { + return MihPackageToolBody( + borderOn: false, + bodyItem: getBody(), + ); + } + + Widget getBody() { + List links = [ + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Youtube", + web_link: "https://www.youtube.com/@MzansiInnovationHub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Threads", + web_link: "https://www.threads.com/@mzansi.innovation.hub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "TikTok", + web_link: "https://www.tiktok.com/@mzansiinnovationhub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "WhatsApp", + web_link: "https://whatsapp.com/channel/0029Vax3INCIyPtMn8KgeM2F", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Twitch", + web_link: "https://www.twitch.tv/mzansiinnovationhub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Instagram", + web_link: "https://www.instagram.com/mzansi.innovation.hub/", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "X", + web_link: "https://x.com/mzansi_inno_hub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "LinkedIn", + web_link: "https://www.linkedin.com/in/yasien-meth-172352108/", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Facebook", + web_link: "https://www.facebook.com/profile.php?id=61565345762136", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Reddit", + web_link: "https://www.reddit.com/r/Mzani_Innovation_Hub/", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Discord", + web_link: "https://discord.gg/ZtTZYd5d", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "My App", + web_link: "https://app.mzansi-innovation-hub.co.za/about", + ), + ]; + + return Stack( + children: [ + MihSingleChildScroll( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + MihProfileLinks( + links: links, + // links: [], + ), + ], + ), + ), + ], + ); + } +} diff --git a/Frontend/lib/mih_package_components/mih_business_info_card.dart b/Frontend/lib/mih_package_components/mih_business_info_card.dart new file mode 100644 index 00000000..b17b53a6 --- /dev/null +++ b/Frontend/lib/mih_package_components/mih_business_info_card.dart @@ -0,0 +1,703 @@ +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_objects/bookmarked_business.dart'; +import 'package:mzansi_innovation_hub/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_objects/business_review.dart'; +import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart'; +import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart'; +import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart'; +import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_add_bookmark_alert.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_delete_bookmark_alert.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_review_business_window.dart'; +import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart'; +import 'package:provider/provider.dart'; +import 'package:redacted/redacted.dart'; +import 'package:supertokens_flutter/supertokens.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class MihBusinessCard extends StatefulWidget { + final Business business; + final double width; + const MihBusinessCard({ + super.key, + required this.business, + required this.width, + }); + + @override + State createState() => _MihBusinessCardState(); +} + +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( + // redactedColor: Colors.pink, + redactedColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + } + + Future _makePhoneCall(String phoneNumber) async { + String formattedNumber = phoneNumber.replaceAll("-", ""); + final Uri url = Uri(scheme: 'tel', path: formattedNumber); + if (await canLaunchUrl(url)) { + await launchUrl(url); + } else { + MihAlertServices().errorBasicAlert( + "Error Making Call", + "We couldn't open your phone app to call $formattedNumber. To fix this, make sure you have a phone application installed and it's set as your default dialer.", + context, + ); + } + } + + String? _encodeQueryParameters(Map params) { + return params.entries + .map((MapEntry e) => + '${Uri.encodeComponent(e.key)}=${Uri.encodeComponent(e.value)}') + .join('&'); + } + + Future _launchEmail( + String recipient, String subject, String body) async { + final Uri emailLaunchUri = Uri( + scheme: 'mailto', + path: recipient, + query: _encodeQueryParameters({ + 'subject': subject, + 'body': body, + }), + ); + + if (await canLaunchUrl(emailLaunchUri)) { + await launchUrl(emailLaunchUri); + } else { + MihAlertServices().errorBasicAlert( + "Error Creating Email", + "We couldn't launch your email app to send a message to $recipient. To fix this, please confirm that you have an email application installed and that it's set as your default.", + context, + ); + } + } + + Future _launchGoogleMapsWithUrl({ + required double latitude, + required double longitude, + String? label, + }) async { + final Uri googleMapsUrl = Uri.parse( + 'https://www.google.com/maps/search/?api=1&query=$latitude,$longitude${label != null ? '&query_place_id=' : ''}', + ); + try { + if (await canLaunchUrl(googleMapsUrl)) { + await launchUrl(googleMapsUrl); + } else { + MihAlertServices().errorBasicAlert( + "Error Opening Maps", + "There was an issue opening maps for ${widget.business.Name}. 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.", + context, + ); + } + } catch (e) { + MihAlertServices().errorBasicAlert( + "Error Opening Maps", + "There was an issue opening maps for ${widget.business.Name}. 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.", + context, + ); + } + } + + 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 { + MihAlertServices().errorBasicAlert( + "Error Opening Website", + "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.", + context, + ); + } + } catch (e) { + MihAlertServices().errorBasicAlert( + "Error Opening Website", + "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.", + context, + ); + } + } + + Widget _buildContactInfo( + String label, + String subLabel, + IconData icon, + Color? iconColor, + bool redacted, + Function()? ontap, + ) { + return Material( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + child: InkWell( + onTap: ontap, + splashColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark") + .withOpacity(0.2), + borderRadius: BorderRadius.circular(15), + child: Padding( + padding: EdgeInsetsGeometry.symmetric( + // vertical: 5, + horizontal: 25, + ), + child: Row( + children: [ + Container( + width: 45, + height: 45, + decoration: BoxDecoration( + color: iconColor, + borderRadius: BorderRadius.circular(15), + ), + padding: const EdgeInsets.all(5.0), + child: FittedBox( + child: Icon( + icon, + // size: 35, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + ).redacted( + context: context, + redact: redacted, + configuration: getRedactedConfiguration(), + ), + SizedBox(width: 20), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + label, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + height: 1.0, + ), + ).redacted( + context: context, + redact: redacted, + configuration: getRedactedConfiguration(), + ), + Text( + subLabel, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w700, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ).redacted( + context: context, + redact: redacted, + configuration: getRedactedConfiguration(), + ), + ], + ), + ), + ], + ), + ), + ), + ); + } + + Future getUserReview() async { + String user_id = await SuperTokens.getUserId(); + return await MihMzansiDirectoryServices().getUserReviewOfBusiness( + user_id, + widget.business.business_id, + ); + } + + Future getUserBookmark() async { + String user_id = await SuperTokens.getUserId(); + return await MihMzansiDirectoryServices().getUserBookmarkOfBusiness( + user_id, + widget.business.business_id, + ); + } + + bool isValidGps(String coordinateString) { + final RegExp gpsRegex = RegExp( + r"^-?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*-?(1[0-7]\d(\.\d+)?|180(\.0+)?|\d{1,2}(\.\d+)?)$"); + return gpsRegex.hasMatch(coordinateString); + } + + @override + void initState() { + super.initState(); + _checkUserSession(); + _businessReviewFuture = getUserReview(); + _bookmarkedBusinessFuture = getUserBookmark(); + } + + @override + Widget build(BuildContext context) { + // double screenWidth = MediaQuery.of(context).size.width; + return Consumer2( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + MzansiDirectoryProvider directoryProvider, Widget? child) { + return Material( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark") + .withValues(alpha: 0.6), + borderRadius: BorderRadius.circular(25), + elevation: 10, + shadowColor: Colors.black, + child: Container( + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + borderRadius: BorderRadius.circular(10), + ), + child: Column( + children: [ + const SizedBox(height: 10), + _buildContactInfo( + "Call", + "Give us a quick call.", + Icons.phone, + MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + false, + () { + // print("Calling ${widget.cellNumber}"); + _makePhoneCall(widget.business.contact_no); + }, + ), + Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + _buildContactInfo( + "Email", + "Send us an email.", + Icons.email, + MihColors.getPinkColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + false, + () { + // print("Emailing ${widget.email}"); + _launchEmail( + widget.business.bus_email, + "Inquiery about ${widget.business.Name}", + "Dear ${widget.business.Name},\n\nI would like to inquire about your services.\n\nBest regards,\n", + ); + }, + ), + Visibility( + visible: isValidGps(widget.business.gps_location), + child: Column( + children: [ + Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + _buildContactInfo( + "Location", + "Come visit us.", + Icons.location_on, + MihColors.getOrangeColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + false, + () { + final latitude = double.parse( + widget.business.gps_location.split(',')[0]); + final longitude = double.parse( + widget.business.gps_location.split(',')[1]); + _launchGoogleMapsWithUrl( + latitude: latitude, + longitude: longitude, + ); + }, + ), + ], + ), + ), + Visibility( + visible: widget.business.website.isNotEmpty && + widget.business.website != "", + child: Column( + children: [ + Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + _buildContactInfo( + "Website", + "Find out more about us.", + Icons.vpn_lock, + MihColors.getRedColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + false, + () { + _launchWebsite(widget.business.website); + }, + ), + ], + ), + ), + FutureBuilder( + future: _businessReviewFuture, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == + ConnectionState.waiting) { + // return const SizedBox.shrink(); + return Column( + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 10.0), + child: Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + Container( + child: _buildContactInfo( + "Loading Rating", + "Loading your rating.", + Icons.star_rate_rounded, + MihColors.getYellowColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + true, + null, + ), + ).redacted(context: context, redact: true), + ], + ); + } else { + BusinessReview? businessReview = asyncSnapshot.data; + String ratingDisplayTitle = ""; + if (businessReview == null) { + ratingDisplayTitle = "Rate Us"; + } else { + ratingDisplayTitle = "Update Rating"; + } + return Column( + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 10.0), + child: Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + _buildContactInfo( + ratingDisplayTitle, + "Let us know how we are doing.", + Icons.star_rate_rounded, + MihColors.getYellowColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + false, + () { + businessReviewRatingWindow(directoryProvider, + businessReview, true, widget.width); + }, + ), + ], + ); + } + }, + ), + FutureBuilder( + future: _bookmarkedBusinessFuture, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == + ConnectionState.waiting) { + // return const SizedBox.shrink(); + return Column( + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 10.0), + child: Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + Container( + child: _buildContactInfo( + "Loading Bookmark", + "Loading your bookmark.", + Icons.bookmark_add_rounded, + MihColors.getBluishPurpleColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + true, + null, + ), + ), + ], + ); + } else { + BookmarkedBusiness? bookmarkBusiness = asyncSnapshot.data; + String bookmarkDisplayTitle = ""; + if (bookmarkBusiness == null) { + bookmarkDisplayTitle = "Bookmark Us"; + } else { + bookmarkDisplayTitle = "Remove Bookmark"; + } + return Column( + children: [ + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 10.0), + child: Divider( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + _buildContactInfo( + bookmarkDisplayTitle, + "Save us for later.", + bookmarkBusiness == null + ? Icons.bookmark_add_rounded + : Icons.bookmark_remove_rounded, + MihColors.getBluishPurpleColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + false, + () { + // _launchWebsite(widget.website); + if (bookmarkBusiness == null) { + showAddBookmarkAlert(); + } else { + showDeleteBookmarkAlert(bookmarkBusiness); + } + }, + ), + ], + ); + } + }, + ), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 10.0), + // child: Divider( + // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + // ), + // _buildContactInfo( + // "Bookmark", + // "Save us for later.", + // Icons.bookmark_add_rounded, + // MihColors.getBluishPurpleColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // () { + // // _launchWebsite(widget.website); + // print("Saving ${widget.business.Name} to Directory"); + // showBookmarkAlert(); + // }, + // ), + const SizedBox(height: 10), + // Padding( + // padding: const EdgeInsets.symmetric(horizontal: 10.0), + // child: Divider( + // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + // ), + // ), + ], + ), + ), + ); + }, + ); + } + + Future businessReviewRatingWindow( + MzansiDirectoryProvider directoryProvider, + BusinessReview? myReview, + bool previouslyRated, + double width) async { + if (_isUserSignedIn) { + showDialog( + barrierDismissible: false, + context: context, + builder: (context) => MihReviewBusinessWindow( + business: widget.business, + businessReview: myReview, + screenWidth: width, + readOnly: false, + onSuccessDismissPressed: () async { + List? businessSearchResults = []; + businessSearchResults = await MihBusinessDetailsServices() + .searchBusinesses(directoryProvider.searchTerm, + directoryProvider.businessTypeFilter, context); + Map> busImagesUrl = {}; + Future businessLogoUrl; + for (var bus in businessSearchResults) { + businessLogoUrl = MihFileApi.getMinioFileUrl(bus.logo_path); + busImagesUrl[bus.business_id] = businessLogoUrl; + } + directoryProvider.setSearchedBusinesses( + searchedBusinesses: businessSearchResults, + businessesImagesUrl: busImagesUrl, + ); + setState(() { + _businessReviewFuture = getUserReview(); + }); + }, + ), + ); + } else { + showSignInRequiredAlert(); + } + } + + void showAddBookmarkAlert() { + if (_isUserSignedIn) { + showDialog( + barrierDismissible: false, + context: context, + builder: (context) => MihAddBookmarkAlert( + business: widget.business, + onSuccessDismissPressed: () async { + _bookmarkedBusinessFuture = getUserBookmark(); + }, + ), + ); + } else { + showSignInRequiredAlert(); + } + } + + void showDeleteBookmarkAlert(BookmarkedBusiness? bookmarkBusiness) { + if (_isUserSignedIn) { + showDialog( + barrierDismissible: false, + context: context, + builder: (context) => MihDeleteBookmarkAlert( + business: widget.business, + bookmarkBusiness: bookmarkBusiness, + onSuccessDismissPressed: () { + _bookmarkedBusinessFuture = getUserBookmark(); + }, + // startUpSearch: widget.startUpSearch, + )); + } else { + showSignInRequiredAlert(); + } + } + + void showSignInRequiredAlert() { + showDialog( + barrierDismissible: false, + context: context, + builder: (context) { + return MihPackageWindow( + fullscreen: false, + windowTitle: null, + onWindowTapClose: () { + context.pop(); + }, + windowBody: Column( + children: [ + Icon( + MihIcons.mihLogo, + size: 125, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + const SizedBox(height: 10), + Text( + "Let's Get Started", + textAlign: TextAlign.center, + style: TextStyle( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + fontSize: 25, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 15), + 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, + ), + ), + ), + ), + ], + ), + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_package_components/mih_circle_avatar.dart b/Frontend/lib/mih_package_components/mih_circle_avatar.dart index 68cb393f..c44c72a3 100644 --- a/Frontend/lib/mih_package_components/mih_circle_avatar.dart +++ b/Frontend/lib/mih_package_components/mih_circle_avatar.dart @@ -161,7 +161,7 @@ class _MihCircleAvatarState extends State { } }, icon: Icon( - Icons.edit, + Icons.camera_alt, ), ), ), diff --git a/Frontend/lib/mih_package_components/mih_package_tile.dart b/Frontend/lib/mih_package_components/mih_package_tile.dart index a8f46b31..5496841d 100644 --- a/Frontend/lib/mih_package_components/mih_package_tile.dart +++ b/Frontend/lib/mih_package_components/mih_package_tile.dart @@ -167,40 +167,34 @@ class _MihPackageTileState extends State { @override Widget build(BuildContext context) { return Container( - // alignment: Alignment.topCenter, + alignment: Alignment.topCenter, // color: Colors.black, - // width: widget.iconSize, - // height: widget.iconSize + widget.iconSize / 3, + width: widget.iconSize, + height: widget.iconSize, child: GestureDetector( onTap: () async { authenticateUser(); }, onLongPress: null, // Do this later child: Column( + mainAxisAlignment: MainAxisAlignment.center, children: [ - Flexible( - flex: 3, - child: LayoutBuilder( - builder: (context, constraints) { - double iconHeight = constraints.maxWidth; - return Container( - width: iconHeight, - height: iconHeight, - child: - FittedBox(fit: BoxFit.fitHeight, child: widget.appIcon), - ); - }, + Expanded( + child: FittedBox( + fit: BoxFit.contain, + alignment: Alignment.center, + child: widget.appIcon, ), ), const SizedBox(height: 10), - Flexible( - flex: 1, + Padding( + // Add a little padding for better visual spacing + padding: const EdgeInsets.symmetric(horizontal: 4.0), child: FittedBox( child: Text( widget.appName, - textAlign: TextAlign.center, - // softWrap: true, - // overflow: TextOverflow.visible, + textAlign: TextAlign.center, // This centers the text content + maxLines: 1, // Allow up to 2 lines to prevent clipping style: TextStyle( color: widget.textColor, fontSize: 20.0, @@ -208,7 +202,7 @@ class _MihPackageTileState extends State { ), ), ), - ) + ), ], ), ), diff --git a/Frontend/lib/mih_package_components/mih_profile_links.dart b/Frontend/lib/mih_package_components/mih_profile_links.dart new file mode 100644 index 00000000..29e7acc0 --- /dev/null +++ b/Frontend/lib/mih_package_components/mih_profile_links.dart @@ -0,0 +1,165 @@ +import 'package:flutter/material.dart'; +import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_objects/profile_link.dart'; +import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tile.dart'; +import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart'; +import 'package:provider/provider.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class MihProfileLinks extends StatefulWidget { + final List links; + final double? buttonSize; + final bool? paddingOn; + const MihProfileLinks({ + super.key, + required this.links, + this.buttonSize, + this.paddingOn, + }); + + @override + State createState() => _MihProfileLinksState(); +} + +class _MihProfileLinksState extends State { + Widget displayLinkButton(ProfileLink link) { + IconData iconData; + Color iconColor; + switch (link.destination.toLowerCase()) { + case "youtube": + iconData = FontAwesomeIcons.youtube; + iconColor = const Color(0xFFFF0000); + break; + case "tiktok": + iconData = FontAwesomeIcons.tiktok; + iconColor = const Color(0xFF000000); + break; + case "twitch": + iconData = FontAwesomeIcons.twitch; + iconColor = const Color(0xFF6441a5); + break; + case "threads": + iconData = FontAwesomeIcons.threads; + iconColor = const Color(0xFF000000); + break; + case "whatsapp": + iconData = FontAwesomeIcons.whatsapp; + iconColor = const Color(0xFF25D366); + break; + case "instagram": + iconData = FontAwesomeIcons.instagram; + iconColor = const Color(0xFFF56040); + break; + case "x": + iconData = FontAwesomeIcons.xTwitter; + iconColor = const Color(0xFF000000); + break; + case "linkedin": + iconData = FontAwesomeIcons.linkedin; + iconColor = const Color(0xFF0a66c2); + break; + case "facebook": + iconData = FontAwesomeIcons.facebook; + iconColor = const Color(0xFF4267B2); + break; + case "reddit": + iconData = FontAwesomeIcons.reddit; + iconColor = const Color(0xFFFF4500); + break; + case "discord": + iconData = FontAwesomeIcons.discord; + iconColor = const Color(0xFF5865F2); + break; + default: + iconData = FontAwesomeIcons.link; + iconColor = MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"); + } + + return MihPackageTile( + onTap: () { + launchSocialUrl(Uri.parse(link.web_link)); + }, + appName: link.destination, + appIcon: Icon( + iconData, + color: iconColor, + ), + iconSize: 200, + textColor: Colors.black, + // MihColors.getPrimaryColor( + // MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ); + } + + Future launchSocialUrl(Uri linkUrl) async { + if (!await launchUrl(linkUrl)) { + throw Exception('Could not launch $linkUrl'); + } + } + + @override + Widget build(BuildContext context) { + double width = MediaQuery.of(context).size.width; + return Consumer( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + Widget? child) { + return Padding( + padding: widget.paddingOn == null || widget.paddingOn! + ? MzansiInnovationHub.of(context)!.theme.screenType == "desktop" + ? EdgeInsets.symmetric(horizontal: width * 0.2) + : EdgeInsets.symmetric(horizontal: width * 0.075) + : EdgeInsetsGeometry.all(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( + width: 500, + padding: EdgeInsets.all(10), + decoration: BoxDecoration( + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + borderRadius: BorderRadius.circular(10), + ), + child: widget.links.isEmpty + ? SizedBox( + height: 35, + child: Text( + "No Profile Links", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 25, + fontWeight: FontWeight.bold, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ) + : Wrap( + alignment: WrapAlignment.center, + runSpacing: 15, + spacing: 15, + children: widget.links.map( + (link) { + return SizedBox( + width: widget.buttonSize ?? 80, + height: widget.buttonSize ?? 80, + child: displayLinkButton(link), + ); + }, + ).toList(), + ), + ), + ), + ); + }, + ); + } +} diff --git a/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart b/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart index 6493c1b2..221e6e37 100644 --- a/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart +++ b/Frontend/lib/mih_packages/about_mih/package_tools/mih_info.dart @@ -1,7 +1,8 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:mzansi_innovation_hub/main.dart'; -import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tile.dart'; +import 'package:mzansi_innovation_hub/mih_objects/profile_link.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; +import 'package:mzansi_innovation_hub/mih_package_components/mih_profile_links.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_install_services.dart'; import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart'; @@ -27,25 +28,6 @@ class MihInfo extends StatefulWidget { class _MihInfoState extends State { late Future _futureUserCount; late Future _futureBusinessCount; - final Uri _tiktokUrl = - Uri.parse('https://www.tiktok.com/@mzansi.innovation.hub'); - final Uri _whatsappUrl = - Uri.parse('https://whatsapp.com/channel/0029Vax3INCIyPtMn8KgeM2F'); - final Uri _twitch = Uri.parse('https://www.twitch.tv/mzansi_innovation_hub'); - final Uri _kick = Uri.parse('https://kick.com/mzansi-innovation-hub'); - final Uri _threadsUrl = - Uri.parse('https://www.threads.net/@mzansi.innovation.hub'); - final Uri _instagramUrl = - Uri.parse('https://www.instagram.com/mzansi.innovation.hub'); - final Uri _youtubeUrl = - Uri.parse('https://www.youtube.com/@mzansiinnovationhub'); - final Uri _xUrl = Uri.parse('https://x.com/mzansi_inno_hub'); - final Uri _linkedinUrl = - Uri.parse('https://www.linkedin.com/company/mzansi-innovation-hub/'); - final Uri _facebookUrl = - Uri.parse('https://www.facebook.com/profile.php?id=61565345762136'); - final Uri _redditUrl = - Uri.parse('https://www.reddit.com/r/Mzani_Innovation_Hub/'); Widget founderBio() { String bio = ""; @@ -190,368 +172,6 @@ class _MihInfoState extends State { ); } - Widget womenForChange() { - String heading = "MIH Stands with Women For Change SA"; - String mission = - "South Africa is facing a devastating crisis of Gender-Based Violence and Femicide (GBVF), with at least 15 women murdered and 117 women reporting rape daily, often at the hands of known individuals, as highlighted by a shocking 33.8% rise in femicide in the last year, despite the existence of the National Strategic Plan on GBVF (NSP GBVF). Due to the government's lack of urgent action and funding for the NSP GBVF's implementation, organizations like Women For Change are urgently calling for the immediate declaration of GBVF as a National Disaster to mobilize resources and political will for decisive action, which must include judicial reforms (like opposing bail and implementing harsher sentences), immediate funding of the NSP GBVF and the new National Council, making the National Sex Offenders Register publicly accessible, and mandating comprehensive GBVF education and continuous public awareness campaigns."; - return SizedBox( - width: 500, - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - heading, - textAlign: TextAlign.center, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 25, - ), - ), - const SizedBox( - height: 10, - ), - Wrap( - alignment: WrapAlignment.center, - crossAxisAlignment: WrapCrossAlignment.center, - spacing: 10, - runSpacing: 10, - children: [ - MihButton( - onPressed: () { - launchSocialUrl( - Uri.parse( - "https://www.tiktok.com/@womenforchange.sa", - ), - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - FaIcon( - FontAwesomeIcons.tiktok, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - const SizedBox(width: 10), - Text( - "@womenforchange.sa", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - MihButton( - onPressed: () { - launchSocialUrl( - Uri.parse( - "https://www.change.org/p/declare-gbvf-a-national-disaster-in-south-africa", - ), - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - FaIcon( - Icons.edit, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - const SizedBox(width: 10), - Text( - "Sign Petition", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - ], - ), - const SizedBox( - height: 10, - ), - Text( - mission, - textAlign: TextAlign.center, - style: const TextStyle( - //fontWeight: FontWeight.bold, - fontSize: 17, - ), - ), - ], - ), - ); - } - - Widget mihSocials() { - String heading = "Follow Our Journey"; - return Column( - children: [ - Text( - heading, - textAlign: TextAlign.center, - style: const TextStyle( - fontWeight: FontWeight.bold, - fontSize: 25, - ), - ), - const SizedBox( - height: 10, - ), - SizedBox( - width: 500, - height: 600, - child: GridView.builder( - padding: const EdgeInsets.only( - // left: width / 10, - // right: width / 10, - // //bottom: height / 5, - // top: 20, - ), - physics: const NeverScrollableScrollPhysics(), - // shrinkWrap: true, - itemCount: getSocialsList().length, - gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( - mainAxisSpacing: 15, maxCrossAxisExtent: 150), - itemBuilder: (context, index) { - return getSocialsList()[index]; - }, - ), - ), - ], - ); - } - - List getSocialsList() { - List socials = []; - socials.add(MihPackageTile( - onTap: () { - launchSocialUrl(_youtubeUrl); - }, - appName: "YouTube", - appIcon: Center( - child: FaIcon( - FontAwesomeIcons.youtube, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - iconSize: 200, - textColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - )); - //================================================================== - socials.add(MihPackageTile( - onTap: () { - launchSocialUrl(_tiktokUrl); - }, - appName: "TikTok", - appIcon: Center( - child: FaIcon( - FontAwesomeIcons.tiktok, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - size: 200, - ), - ), - iconSize: 200, - textColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - )); - //================================================================== - socials.add(MihPackageTile( - onTap: () { - launchSocialUrl(_twitch); - }, - appName: "Twitch", - appIcon: Center( - child: FaIcon( - FontAwesomeIcons.twitch, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - size: 200, - ), - ), - iconSize: 200, - textColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - )); - //================================================================== - socials.add(MihPackageTile( - onTap: () { - launchSocialUrl(_threadsUrl); - }, - appName: "Threads", - appIcon: Center( - child: FaIcon( - FontAwesomeIcons.threads, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - size: 200, - ), - ), - iconSize: 200, - textColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - )); - //================================================================== - socials.add(MihPackageTile( - onTap: () { - launchSocialUrl(_whatsappUrl); - }, - appName: "Whatsapp", - appIcon: Center( - child: FaIcon( - FontAwesomeIcons.whatsapp, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - size: 200, - ), - ), - iconSize: 200, - textColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - )); - //================================================================== - socials.add(MihPackageTile( - onTap: () { - launchSocialUrl(_instagramUrl); - }, - appName: "Instagram", - appIcon: Center( - child: FaIcon( - FontAwesomeIcons.instagram, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - size: 200, - ), - ), - iconSize: 200, - textColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - )); - //================================================================== - - socials.add(MihPackageTile( - onTap: () { - launchSocialUrl(_xUrl); - }, - appName: "X", - appIcon: Center( - child: FaIcon( - FontAwesomeIcons.xTwitter, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - size: 200, - ), - ), - iconSize: 200, - textColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - )); - //================================================================== - socials.add(MihPackageTile( - onTap: () { - launchSocialUrl(_linkedinUrl); - }, - appName: "LinkedIn", - appIcon: Center( - child: FaIcon( - FontAwesomeIcons.linkedin, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - size: 200, - ), - ), - iconSize: 200, - textColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - )); - //================================================================== - socials.add(MihPackageTile( - onTap: () { - launchSocialUrl(_facebookUrl); - }, - appName: "FaceBook", - appIcon: Center( - child: FaIcon( - FontAwesomeIcons.facebook, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - size: 200, - ), - ), - iconSize: 200, - textColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - )); - //================================================================== - socials.add(MihPackageTile( - onTap: () { - launchSocialUrl(_redditUrl); - }, - appName: "Reddit", - appIcon: Center( - child: FaIcon( - FontAwesomeIcons.reddit, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - size: 200, - ), - ), - iconSize: 200, - textColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - )); - //================================================================== - socials.add(MihPackageTile( - onTap: () { - launchSocialUrl(_kick); - }, - appName: "Kick", - appIcon: Center( - child: Text( - "KICK", - style: TextStyle( - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontWeight: FontWeight.bold, - fontSize: 100, - ), - ), - // FaIcon( - // FontAwesomeIcons.tv, - // color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - // size: 200, - // ), - ), - iconSize: 100, - textColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - )); - //================================================================== - return socials; - } - Future launchSocialUrl(Uri linkUrl) async { if (!await launchUrl(linkUrl)) { throw Exception('Could not launch $linkUrl'); @@ -720,6 +340,424 @@ class _MihInfoState extends State { ); } + Widget mihDivider() { + return Padding( + padding: EdgeInsets.symmetric( + vertical: 10.0, + horizontal: 25, + ), + child: Divider( + thickness: 1, + color: MihColors.getGreyColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ); + } + + Widget aboutHeadings() { + return Column( + children: [ + SizedBox( + width: 165, + child: FittedBox( + child: Icon( + MihIcons.mihLogo, + color: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + ), + ), + const SizedBox( + height: 10, + ), + const Text( + "Mzansi Innovation Hub", + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 30, + ), + ), + Text( + "MIH App Version: ${MzansiInnovationHub.of(context)!.theme.getLatestVersion()}", + textAlign: TextAlign.center, + style: const TextStyle( + fontWeight: FontWeight.normal, + fontSize: 15, + ), + ), + const SizedBox( + height: 10, + ), + ], + ); + } + + Widget communityCounter() { + return Column( + children: [ + Wrap( + alignment: WrapAlignment.spaceAround, + crossAxisAlignment: WrapCrossAlignment.center, + spacing: 25, + runSpacing: 10, + children: [ + displayUserCount(), + displayBusinessCount(), + ], + ), + Text( + "The MIH Community", + textAlign: TextAlign.center, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 22, + ), + ), + const SizedBox( + height: 10, + ), + ], + ); + } + + Widget callToActionsButtons() { + return Column( + children: [ + Wrap( + alignment: WrapAlignment.center, + crossAxisAlignment: WrapCrossAlignment.center, + spacing: 10, + runSpacing: 10, + children: [ + MihButton( + onPressed: () { + MihInstallServices().installMihTrigger(context); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + width: 300, + child: getInstallButtonText(), + ), + MihButton( + onPressed: () { + launchSocialUrl( + Uri.parse( + "https://www.youtube.com/playlist?list=PLuT35kJIui0H5kXjxNOZlHoOPZbQLr4qh", + ), + ); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + width: 300, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FaIcon( + FontAwesomeIcons.youtube, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + const SizedBox(width: 10), + Text( + "MIH Beginners Guide", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + MihButton( + onPressed: () { + launchSocialUrl( + Uri.parse( + "https://patreon.com/MzansiInnovationHub?utm_medium=unknown&utm_source=join_link&utm_campaign=creatorshare_creator&utm_content=copyLink", + ), + ); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + width: 300, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FaIcon( + FontAwesomeIcons.patreon, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), + const SizedBox(width: 10), + Text( + "Support Our Journey", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ], + ), + const SizedBox( + height: 10, + ), + ], + ); + } + + Widget womenForChange() { + String heading = "MIH Stands with Women For Change SA"; + String mission = + "South Africa is facing a devastating crisis of Gender-Based Violence and Femicide (GBVF), with at least 15 women murdered and 117 women reporting rape daily, often at the hands of known individuals, as highlighted by a shocking 33.8% rise in femicide in the last year, despite the existence of the National Strategic Plan on GBVF (NSP GBVF). Due to the government's lack of urgent action and funding for the NSP GBVF's implementation, organizations like Women For Change are urgently calling for the immediate declaration of GBVF as a National Disaster to mobilize resources and political will for decisive action, which must include judicial reforms (like opposing bail and implementing harsher sentences), immediate funding of the NSP GBVF and the new National Council, making the National Sex Offenders Register publicly accessible, and mandating comprehensive GBVF education and continuous public awareness campaigns."; + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 25.0), + child: SizedBox( + width: 500, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + heading, + textAlign: TextAlign.center, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 25, + ), + ), + const SizedBox( + height: 10, + ), + Wrap( + alignment: WrapAlignment.center, + crossAxisAlignment: WrapCrossAlignment.center, + spacing: 10, + runSpacing: 10, + children: [ + MihButton( + onPressed: () { + launchSocialUrl( + Uri.parse( + "https://www.tiktok.com/@womenforchange.sa", + ), + ); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + width: 300, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FaIcon( + FontAwesomeIcons.tiktok, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + const SizedBox(width: 10), + Text( + "@womenforchange.sa", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + MihButton( + onPressed: () { + launchSocialUrl( + Uri.parse( + "https://www.change.org/p/declare-gbvf-a-national-disaster-in-south-africa", + ), + ); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + width: 300, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FaIcon( + Icons.edit, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + const SizedBox(width: 10), + Text( + "Sign Petition", + style: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ], + ), + const SizedBox( + height: 10, + ), + Text( + mission, + textAlign: TextAlign.center, + style: const TextStyle( + //fontWeight: FontWeight.bold, + fontSize: 17, + ), + ), + ], + ), + ), + ); + } + + Widget missionAndVission() { + return Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 25.0), + child: Wrap( + alignment: WrapAlignment.start, + crossAxisAlignment: WrapCrossAlignment.start, + spacing: 10, + runSpacing: 10, + children: [ + ourVision(), + ourMission(), + ], + ), + ), + const SizedBox( + height: 10, + ), + ], + ); + } + + Widget founderDetails() { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.max, + children: [ + founderTitle(), + founderBio(), + ], + ); + } + + Widget mihSocials() { + List links = [ + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Youtube", + web_link: "https://www.youtube.com/@MzansiInnovationHub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "TikTok", + web_link: "https://www.tiktok.com/@mzansiinnovationhub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Twitch", + web_link: "https://www.twitch.tv/mzansiinnovationhub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Threads", + web_link: "https://www.threads.com/@mzansi.innovation.hub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "WhatsApp", + web_link: "https://whatsapp.com/channel/0029Vax3INCIyPtMn8KgeM2F", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Instagram", + web_link: "https://www.instagram.com/mzansi.innovation.hub/", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "X", + web_link: "https://x.com/mzansi_inno_hub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "LinkedIn", + web_link: "https://www.linkedin.com/company/mzansi-innovation-hub/", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Facebook", + web_link: "https://www.facebook.com/profile.php?id=61565345762136", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Reddit", + web_link: "https://www.reddit.com/r/Mzani_Innovation_Hub/", + ), + ]; + return Column( + children: [ + Text( + "Follow Our Journey", + textAlign: TextAlign.center, + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 25, + ), + ), + const SizedBox( + height: 10, + ), + MihProfileLinks(links: links), + const SizedBox( + height: 25, + ), + ], + ); + } + @override void initState() { super.initState(); @@ -731,7 +769,6 @@ class _MihInfoState extends State { Widget build(BuildContext context) { return MihPackageToolBody( borderOn: false, - innerHorizontalPadding: 10, bodyItem: getBody(), ); } @@ -742,214 +779,16 @@ class _MihInfoState extends State { MihSingleChildScroll( child: Column( children: [ - SizedBox( - width: 165, - child: FittedBox( - child: Icon( - MihIcons.mihLogo, - color: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - ), - const SizedBox( - height: 10, - ), - const Text( - "Mzansi Innovation Hub", - textAlign: TextAlign.center, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 30, - ), - ), - Text( - "MIH App Version: ${MzansiInnovationHub.of(context)!.theme.getLatestVersion()}", - textAlign: TextAlign.center, - style: const TextStyle( - fontWeight: FontWeight.normal, - fontSize: 15, - ), - ), - const SizedBox( - height: 10, - ), - Wrap( - alignment: WrapAlignment.spaceAround, - crossAxisAlignment: WrapCrossAlignment.center, - spacing: 25, - runSpacing: 10, - children: [ - displayUserCount(), - displayBusinessCount(), - ], - ), - Text( - "The MIH Community", - textAlign: TextAlign.center, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 22, - ), - ), - const SizedBox( - height: 10, - ), - Wrap( - alignment: WrapAlignment.center, - crossAxisAlignment: WrapCrossAlignment.center, - spacing: 10, - runSpacing: 10, - children: [ - MihButton( - onPressed: () { - MihInstallServices().installMihTrigger(context); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: getInstallButtonText(), - ), - MihButton( - onPressed: () { - launchSocialUrl( - Uri.parse( - "https://www.youtube.com/playlist?list=PLuT35kJIui0H5kXjxNOZlHoOPZbQLr4qh", - ), - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - FaIcon( - FontAwesomeIcons.youtube, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - const SizedBox(width: 10), - Text( - "MIH Beginners Guide", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - MihButton( - onPressed: () { - launchSocialUrl( - Uri.parse( - "https://patreon.com/MzansiInnovationHub?utm_medium=unknown&utm_source=join_link&utm_campaign=creatorshare_creator&utm_content=copyLink", - ), - ); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - width: 300, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - FaIcon( - FontAwesomeIcons.patreon, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - const SizedBox(width: 10), - Text( - "Support Our Journey", - style: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ], - ), - ), - ], - ), - const SizedBox( - height: 10, - ), - // // ===================== Divider - Padding( - padding: EdgeInsets.symmetric( - vertical: 10.0, - horizontal: 25, - ), - child: Divider( - thickness: 1, - color: MihColors.getGreyColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 25.0), - child: Wrap( - alignment: WrapAlignment.start, - crossAxisAlignment: WrapCrossAlignment.start, - spacing: 10, - runSpacing: 10, - children: [ - womenForChange(), - ourVision(), - ourMission(), - ], - ), - ), - const SizedBox( - height: 25, - ), - const SizedBox( - height: 10, - ), - // ===================== Divider - Padding( - padding: EdgeInsets.symmetric( - vertical: 10.0, - horizontal: 25, - ), - child: Divider( - thickness: 1, - color: MihColors.getGreyColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), - Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisSize: MainAxisSize.max, - // spacing: 10, - // runSpacing: 10, - children: [ - founderTitle(), - founderBio(), - ], - ), - // ===================== Divider - Padding( - padding: EdgeInsets.symmetric( - vertical: 10.0, - horizontal: 25, - ), - child: Divider( - thickness: 1, - color: MihColors.getGreyColor( - MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - ), - ), + aboutHeadings(), + communityCounter(), + callToActionsButtons(), + mihDivider(), + womenForChange(), + mihDivider(), + missionAndVission(), + mihDivider(), + founderDetails(), + mihDivider(), mihSocials(), ], ), 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 e21ec303..e1b44553 100644 --- a/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart +++ b/Frontend/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart @@ -1,9 +1,11 @@ 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_objects/profile_link.dart'; import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart'; import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart'; +import 'package:mzansi_innovation_hub/mih_package_components/mih_profile_links.dart'; import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart'; import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart'; import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart'; @@ -35,12 +37,100 @@ class _MihPersonalProfileState extends State { ); } + List getTempLinks() { + return [ + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Youtube", + web_link: "https://www.youtube.com/@MzansiInnovationHub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Threads", + web_link: "https://www.threads.com/@mzansi.innovation.hub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "TikTok", + web_link: "https://www.tiktok.com/@mzansiinnovationhub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "WhatsApp", + web_link: "https://whatsapp.com/channel/0029Vax3INCIyPtMn8KgeM2F", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Twitch", + web_link: "https://www.twitch.tv/mzansiinnovationhub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Instagram", + web_link: "https://www.instagram.com/mzansi.innovation.hub/", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "X", + web_link: "https://x.com/mzansi_inno_hub", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "LinkedIn", + web_link: "https://www.linkedin.com/in/yasien-meth-172352108/", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Facebook", + web_link: "https://www.facebook.com/profile.php?id=61565345762136", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Reddit", + web_link: "https://www.reddit.com/r/Mzani_Innovation_Hub/", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "Discord", + web_link: "https://discord.gg/ZtTZYd5d", + ), + ProfileLink( + idprofile_links: 1, + app_id: "1234", + business_id: "", + destination: "My App", + web_link: "https://app.mzansi-innovation-hub.co.za/about", + ), + ]; + } + @override Widget build(BuildContext context) { double screenWidth = MediaQuery.of(context).size.width; return MihPackageToolBody( borderOn: false, - innerHorizontalPadding: 10, bodyItem: getBody(screenWidth), ); } @@ -64,27 +154,50 @@ class _MihPersonalProfileState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ - Center( - child: MihCircleAvatar( - imageFile: mzansiProfileProvider.userProfilePicture, - width: 150, - editable: false, - fileNameController: proPicController, - userSelectedfile: newSelectedProPic, - frameColor: MihColors.getSecondaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - backgroundColor: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - onChange: (selectedImage) { - setState(() { - newSelectedProPic = selectedImage; - }); - }, - key: ValueKey(mzansiProfileProvider.userProfilePicUrl), - ), + Stack( + children: [ + MihCircleAvatar( + imageFile: mzansiProfileProvider.userProfilePicture, + width: 150, + editable: false, + fileNameController: proPicController, + userSelectedfile: newSelectedProPic, + frameColor: MihColors.getSecondaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + backgroundColor: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + onChange: (selectedImage) { + setState(() { + newSelectedProPic = selectedImage; + }); + }, + key: ValueKey(mzansiProfileProvider.userProfilePicUrl), + ), + Positioned( + bottom: 5, + right: 5, + child: MihButton( + onPressed: () { + editProfileWindow(width); + }, + buttonColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + width: 35, + height: 35, + child: Icon( + Icons.edit, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + ), + ), + ], ), + const SizedBox(height: 10.0), FittedBox( child: Text( mzansiProfileProvider.user!.username.isNotEmpty @@ -134,7 +247,7 @@ class _MihPersonalProfileState extends State { child: Text( mzansiProfileProvider.user!.purpose.isNotEmpty ? mzansiProfileProvider.user!.purpose - : "No Personal Mission added yet", + : "", textAlign: TextAlign.center, style: TextStyle( fontSize: 15, @@ -146,30 +259,36 @@ class _MihPersonalProfileState extends State { ), ), ), - const SizedBox(height: 30.0), - Center( - child: MihButton( - onPressed: () { - // Connect with the user - editProfileWindow(width); - }, - buttonColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - width: 300, - child: Text( - mzansiProfileProvider.user!.username.isEmpty - ? "Set Up Profile" - : "Edit Profile", - style: TextStyle( - color: MihColors.getPrimaryColor( + const SizedBox(height: 15.0), + Stack( + children: [ + MihProfileLinks( + // links: mzansiProfileProvider.personalLinks, + links: getTempLinks(), + buttonSize: 80, + paddingOn: false, + ), + Positioned( + top: 5, + left: 5, + child: MihButton( + onPressed: () { + editProfileWindow(width); + }, + buttonColor: MihColors.getGreenColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - fontSize: 20, - fontWeight: FontWeight.bold, + width: 35, + height: 35, + child: Icon( + Icons.link, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), ), ), - ), + ], ), ], ), diff --git a/Frontend/lib/mih_providers/mzansi_profile_provider.dart b/Frontend/lib/mih_providers/mzansi_profile_provider.dart index 7bf715dc..c35483d8 100644 --- a/Frontend/lib/mih_providers/mzansi_profile_provider.dart +++ b/Frontend/lib/mih_providers/mzansi_profile_provider.dart @@ -4,6 +4,7 @@ import 'package:mzansi_innovation_hub/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_objects/business_employee.dart'; import 'package:mzansi_innovation_hub/mih_objects/business_user.dart'; +import 'package:mzansi_innovation_hub/mih_objects/profile_link.dart'; import 'package:mzansi_innovation_hub/mih_objects/user_consent.dart'; class MzansiProfileProvider extends ChangeNotifier { @@ -23,6 +24,7 @@ class MzansiProfileProvider extends ChangeNotifier { List? employeeList; List userSearchResults = []; bool hideBusinessUserDetails; + List personalLinks = []; MzansiProfileProvider({ this.personalHome = true, @@ -149,4 +151,9 @@ class MzansiProfileProvider extends ChangeNotifier { this.userSearchResults = userSearchResults; notifyListeners(); } + + void setPersonalLinks({required List personalLinks}) { + this.personalLinks = personalLinks; + notifyListeners(); + } }