MIH Profile Links

This commit is contained in:
2026-05-27 15:36:56 +02:00
parent 33d07b1617
commit 052f937027
30 changed files with 2240 additions and 499 deletions
@@ -725,79 +725,101 @@ class _MihInfoState extends State<MihInfo> {
idprofile_links: 1,
app_id: "1234",
business_id: "",
destination: "Youtube",
web_link: "https://www.youtube.com/@MzansiInnovationHub",
site_name: "Youtube",
custom_name: "",
destination: "https://www.youtube.com/@MzansiInnovationHub",
order: 1,
),
ProfileLink(
idprofile_links: 1,
app_id: "1234",
business_id: "",
destination: "TikTok",
web_link: "https://www.tiktok.com/@mzansiinnovationhub",
site_name: "TikTok",
custom_name: "",
destination: "https://www.tiktok.com/@mzansiinnovationhub",
order: 2,
),
ProfileLink(
idprofile_links: 1,
app_id: "1234",
business_id: "",
destination: "Twitch",
web_link: "https://www.twitch.tv/mzansiinnovationhub",
site_name: "Twitch",
custom_name: "",
destination: "https://www.twitch.tv/mzansiinnovationhub",
order: 3,
),
ProfileLink(
idprofile_links: 1,
app_id: "1234",
business_id: "",
destination: "Threads",
web_link: "https://www.threads.com/@mzansi.innovation.hub",
site_name: "Threads",
custom_name: "",
destination: "https://www.threads.com/@mzansi.innovation.hub",
order: 4,
),
ProfileLink(
idprofile_links: 1,
app_id: "1234",
business_id: "",
destination: "WhatsApp",
web_link: "https://whatsapp.com/channel/0029Vax3INCIyPtMn8KgeM2F",
site_name: "WhatsApp",
custom_name: "",
destination: "https://whatsapp.com/channel/0029Vax3INCIyPtMn8KgeM2F",
order: 5,
),
ProfileLink(
idprofile_links: 1,
app_id: "1234",
business_id: "",
destination: "Instagram",
web_link: "https://www.instagram.com/mzansi.innovation.hub/",
site_name: "Instagram",
custom_name: "",
destination: "https://www.instagram.com/mzansi.innovation.hub/",
order: 6,
),
ProfileLink(
idprofile_links: 1,
app_id: "1234",
business_id: "",
destination: "X",
web_link: "https://x.com/mzansi_inno_hub",
site_name: "X",
custom_name: "",
destination: "https://x.com/mzansi_inno_hub",
order: 7,
),
ProfileLink(
idprofile_links: 1,
app_id: "1234",
business_id: "",
destination: "LinkedIn",
web_link: "https://www.linkedin.com/company/mzansi-innovation-hub/",
site_name: "LinkedIn",
custom_name: "",
destination: "https://www.linkedin.com/company/mzansi-innovation-hub/",
order: 8,
),
ProfileLink(
idprofile_links: 1,
app_id: "1234",
business_id: "",
destination: "Facebook",
web_link: "https://www.facebook.com/profile.php?id=61565345762136",
site_name: "Facebook",
custom_name: "",
destination: "https://www.facebook.com/profile.php?id=61565345762136",
order: 9,
),
ProfileLink(
idprofile_links: 1,
app_id: "1234",
business_id: "",
destination: "Reddit",
web_link: "https://www.reddit.com/r/Mzani_Innovation_Hub/",
site_name: "Reddit",
custom_name: "",
destination: "https://www.reddit.com/r/Mzani_Innovation_Hub/",
order: 10,
),
ProfileLink(
idprofile_links: 1,
app_id: "1234",
business_id: "",
destination: "Git",
web_link:
site_name: "Git",
custom_name: "",
destination:
"https://git.mzansi-innovation-hub.co.za/yaso_meth/mih-project",
order: 11,
),
];
return Column(
@@ -130,7 +130,7 @@ class _MihMineSweeperLeaderBoardState extends State<MihMineSweeperLeaderBoard> {
children: [
const SizedBox(height: 50),
Icon(
MihIcons.mineSweeper,
MihIcons.mihMinesweeper,
size: 165,
color: MihColors.secondary(),
),
@@ -596,7 +596,7 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
children: [
const SizedBox(height: 50),
Icon(
MihIcons.mineSweeper,
MihIcons.mihMinesweeper,
size: 165,
color: MihColors.secondary(),
),
@@ -780,7 +780,7 @@ class _MineSweeperGameState extends State<MineSweeperGame> {
_timer != null && !kIsWeb && (Platform.isAndroid || Platform.isIOS)
? MihBannerAd()
: SizedBox(),
SizedBox(height: 15),
SizedBox(height: 10),
],
);
},
@@ -134,7 +134,7 @@ class _MihMineSweeperLeaderBoardState extends State<MyScoreBoard> {
children: [
const SizedBox(height: 50),
Icon(
MihIcons.mineSweeper,
MihIcons.mihMinesweeper,
size: 165,
color: MihColors.secondary(),
),
@@ -40,7 +40,7 @@ class _MzansiBusinessProfileViewState extends State<MzansiBusinessProfileView> {
extra: true,
);
} else {
KenLogger.success("Business found: ${biz.Name}");
// KenLogger.success("Business found: ${biz.Name}");
directoryProvider.setSelectedBusiness(business: biz);
}
}
@@ -1,9 +1,13 @@
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:custom_rating_bar/custom_rating_bar.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_banner_ad.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_business_info_card_v2.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
@@ -53,136 +57,142 @@ class _MihBusinessDetailsViewState extends State<MihBusinessDetailsView> {
return Consumer<MzansiDirectoryProvider>(
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
Widget? child) {
return Stack(
return Column(
children: [
MihSingleChildScroll(
scrollbarOn: true,
child: Padding(
padding: MzansiInnovationHub.of(context)!.theme.screenType ==
"desktop"
? EdgeInsets.symmetric(horizontal: width * 0.2)
: EdgeInsets.symmetric(horizontal: width * 0),
child: Column(
children: [
FutureBuilder(
future: futureImageUrl,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState ==
ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "") {
return MihCircleAvatar(
imageFile: CachedNetworkImageProvider(
asyncSnapshot.requireData),
width: profilePictureWidth,
expandable: true,
editable: false,
fileNameController: TextEditingController(),
userSelectedfile: file,
frameColor: MihColors.secondary(),
backgroundColor: MihColors.primary(),
onChange: () {},
);
Expanded(
child: MihSingleChildScroll(
scrollbarOn: true,
child: Padding(
padding: MzansiInnovationHub.of(context)!.theme.screenType ==
"desktop"
? EdgeInsets.symmetric(horizontal: width * 0.2)
: EdgeInsets.symmetric(horizontal: width * 0),
child: Column(
children: [
FutureBuilder(
future: futureImageUrl,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState ==
ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "") {
return MihCircleAvatar(
imageFile: CachedNetworkImageProvider(
asyncSnapshot.requireData),
width: profilePictureWidth,
expandable: true,
editable: false,
fileNameController: TextEditingController(),
userSelectedfile: file,
frameColor: MihColors.secondary(),
backgroundColor: MihColors.primary(),
onChange: () {},
);
} else {
return Icon(
MihIcons.iDontKnow,
size: profilePictureWidth,
color: MihColors.secondary(),
);
}
} else {
return Icon(
MihIcons.iDontKnow,
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.secondary(),
);
}
} else {
return Icon(
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.secondary(),
);
}
}),
// Center(
// child: MihCircleAvatar(
// imageFile: widget.logoImage,
// width: 150,
// editable: false,
// fileNameController: fileNameController,
// userSelectedfile: imageFile,
// frameColor:
// MihColors.secondary(),
// backgroundColor:
// MihColors.primary(),
// onChange: (selectedfile) {
// setState(() {
// imageFile = selectedfile;
// });
// },
// ),
// ),
FittedBox(
child: Text(
directoryProvider.selectedBusiness!.Name,
style: TextStyle(
fontSize: 35,
fontWeight: FontWeight.bold,
color: MihColors.secondary(),
),
),
),
FittedBox(
child: Text(
directoryProvider.selectedBusiness!.type,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: MihColors.secondary(),
),
),
),
RatingBar.readOnly(
size: 50,
alignment: Alignment.center,
filledIcon: Icons.star,
emptyIcon: Icons.star_border,
halfFilledIcon: Icons.star_half,
filledColor: MihColors.yellow(),
// MihColors.primary(),
emptyColor: MihColors.secondary(),
halfFilledColor: MihColors.yellow(),
// MihColors.primary(),
isHalfAllowed: true,
initialRating:
directoryProvider.selectedBusiness!.rating.isNotEmpty
? double.parse(
directoryProvider.selectedBusiness!.rating)
: 0,
maxRating: 5,
),
const SizedBox(height: 5),
Center(
child: SizedBox(
width: 700,
}),
// Center(
// child: MihCircleAvatar(
// imageFile: widget.logoImage,
// width: 150,
// editable: false,
// fileNameController: fileNameController,
// userSelectedfile: imageFile,
// frameColor:
// MihColors.secondary(),
// backgroundColor:
// MihColors.primary(),
// onChange: (selectedfile) {
// setState(() {
// imageFile = selectedfile;
// });
// },
// ),
// ),
FittedBox(
child: Text(
directoryProvider
.selectedBusiness!.mission_vision.isNotEmpty
? directoryProvider
.selectedBusiness!.mission_vision
: "No Mission & Vision added yet",
textAlign: TextAlign.center,
directoryProvider.selectedBusiness!.Name,
style: TextStyle(
fontSize: 15,
fontSize: 35,
fontWeight: FontWeight.bold,
color: MihColors.secondary(),
),
),
),
),
const SizedBox(height: 20),
MihBusinessCardV2(
business: directoryProvider.selectedBusiness!,
width: width,
),
],
FittedBox(
child: Text(
directoryProvider.selectedBusiness!.type,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: MihColors.secondary(),
),
),
),
RatingBar.readOnly(
size: 50,
alignment: Alignment.center,
filledIcon: Icons.star,
emptyIcon: Icons.star_border,
halfFilledIcon: Icons.star_half,
filledColor: MihColors.yellow(),
// MihColors.primary(),
emptyColor: MihColors.secondary(),
halfFilledColor: MihColors.yellow(),
// MihColors.primary(),
isHalfAllowed: true,
initialRating: directoryProvider
.selectedBusiness!.rating.isNotEmpty
? double.parse(
directoryProvider.selectedBusiness!.rating)
: 0,
maxRating: 5,
),
const SizedBox(height: 5),
Center(
child: SizedBox(
width: 700,
child: Text(
directoryProvider
.selectedBusiness!.mission_vision.isNotEmpty
? directoryProvider
.selectedBusiness!.mission_vision
: "No Mission & Vision added yet",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: MihColors.secondary(),
),
),
),
),
const SizedBox(height: 20),
MihBusinessCardV2(
business: directoryProvider.selectedBusiness!,
width: width,
),
],
),
),
),
),
!kIsWeb && (Platform.isAndroid || Platform.isIOS)
? MihBannerAd()
: SizedBox(),
SizedBox(height: 10),
],
);
},
@@ -63,7 +63,7 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
Future<void> saveImage(Uint8List imageBytes) async {
final String filename =
"${business.Name}_QR_Code_${DateTime.now().millisecondsSinceEpoch}.png";
"${business.Name}_QR_Code_${DateTime.now().millisecondsSinceEpoch}";
if (kIsWeb) {
await FileSaver.instance.saveFile(
name: filename,
@@ -0,0 +1,185 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/main.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_profile_links_service.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:provider/provider.dart';
class MihAddUserProfileLinksWindow extends StatefulWidget {
const MihAddUserProfileLinksWindow({super.key});
@override
State<MihAddUserProfileLinksWindow> createState() =>
_MihAddUserProfileLinksWindowState();
}
class _MihAddUserProfileLinksWindowState
extends State<MihAddUserProfileLinksWindow> {
final _formKey = GlobalKey<FormState>();
List<String> _dropdowOptions = [
"YouTube",
"TikTok",
"Twitch",
"Threads",
"WhatsApp",
"Instagram",
"X",
"LinkedIn",
"Facebook",
"Reddit",
"Discord",
"Git",
"Telegram",
"Pinterest",
"Snapchat",
"Messenger",
"Medium",
"Substack",
"Spotify",
"YT Music",
"Apple Music",
"Patreon",
"Loolio",
"WeChat",
"Other"
];
TextEditingController _dropdownLinkNameController = TextEditingController();
TextEditingController _linkNameController = TextEditingController();
TextEditingController _destinationController = TextEditingController();
void successPopUp(String title, String message, int packageIndex) {
MihAlertServices().successBasicAlert(
title,
message,
context,
);
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
_dropdowOptions.sort();
bool isOtherSelected = _dropdownLinkNameController.text == "Other";
return Consumer<MzansiProfileProvider>(
builder: (
BuildContext context,
MzansiProfileProvider profileProvider,
Widget? child,
) {
return MihPackageWindow(
fullscreen: false,
windowTitle: "Add Link",
onWindowTapClose: () {
_dropdownLinkNameController.clear();
_destinationController.clear();
_linkNameController.clear();
Navigator.pop(context);
},
windowBody: Padding(
padding:
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: screenWidth * 0.05)
: EdgeInsets.symmetric(horizontal: screenWidth * 0),
child: Column(
children: [
MihForm(
formKey: _formKey,
formFields: [
MihDropdownField(
controller: _dropdownLinkNameController,
hintText: 'Site Name',
dropdownOptions: _dropdowOptions,
requiredText: true,
editable: true,
enableSearch: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
onSelected: (value) {
setState(() {});
},
),
const SizedBox(height: 10),
MihTextFormField(
fillColor: MihColors.secondary(),
inputColor: MihColors.primary(),
controller: _linkNameController,
hintText: "Custom Name",
requiredText: isOtherSelected,
validator: (value) {
if (isOtherSelected) {
return MihValidationServices().isEmpty(value);
}
return null;
},
),
const SizedBox(height: 10),
MihTextFormField(
fillColor: MihColors.secondary(),
inputColor: MihColors.primary(),
controller: _destinationController,
hintText: "Link",
requiredText: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 20),
MihButton(
onPressed: () async {
if (_formKey.currentState!.validate()) {
MihProfileLinksServices.loadingPopUp(context);
int statusCode =
await MihProfileLinksServices.addProfileLink(
profileProvider,
profileProvider.user!.app_id,
"",
_dropdownLinkNameController.text,
_linkNameController.text,
_destinationController.text,
profileProvider.personalLinks.length + 1,
);
KenLogger.success("Status COde: $statusCode");
context.pop();
if (statusCode == 201) {
await MihProfileLinksServices.getUserProfileLinks(
profileProvider,
profileProvider.user!.app_id,
);
context.pop();
successPopUp(
"Profile Link Added",
"You have successfully added a new link to your profile",
0);
} else {
MihAlertServices().internetConnectionAlert(context);
}
} else {
MihAlertServices().inputErrorAlert(context);
}
},
buttonColor: MihColors.green(),
width: 300,
child: Text(
"Add",
style: TextStyle(
color: MihColors.primary(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
],
),
),
);
},
);
}
}
@@ -0,0 +1,195 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_objects/profile_link.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_profile_links_service.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:provider/provider.dart';
class MihEditUserProfileLinksWindow extends StatefulWidget {
final ProfileLink link;
const MihEditUserProfileLinksWindow({
super.key,
required this.link,
});
@override
State<MihEditUserProfileLinksWindow> createState() =>
_MihEditUserProfileLinksWindowState();
}
class _MihEditUserProfileLinksWindowState
extends State<MihEditUserProfileLinksWindow> {
final _formKey = GlobalKey<FormState>();
List<String> _dropdowOptions = [
"YouTube",
"TikTok",
"Twitch",
"Threads",
"WhatsApp",
"Instagram",
"X",
"LinkedIn",
"Facebook",
"Reddit",
"Discord",
"Git",
"Telegram",
"Pinterest",
"Snapchat",
"Messenger",
"Medium",
"Substack",
"Spotify",
"YT Music",
"Apple Music",
"Patreon",
"Loolio",
"WeChat",
"Other"
];
TextEditingController _dropdownLinkNameController = TextEditingController();
TextEditingController _linkNameController = TextEditingController();
TextEditingController _destinationController = TextEditingController();
void successPopUp(String title, String message, int packageIndex) {
MihAlertServices().successBasicAlert(
title,
message,
context,
);
}
@override
void initState() {
super.initState();
_dropdownLinkNameController.text = widget.link.site_name;
_linkNameController.text = widget.link.custom_name;
_destinationController.text = widget.link.destination;
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
_dropdowOptions.sort();
bool isOtherSelected = _dropdownLinkNameController.text == "Other";
return Consumer<MzansiProfileProvider>(
builder: (
BuildContext context,
MzansiProfileProvider profileProvider,
Widget? child,
) {
return MihPackageWindow(
fullscreen: false,
windowTitle: "Update Link",
onWindowTapClose: () {
_dropdownLinkNameController.clear();
_destinationController.clear();
_linkNameController.clear();
Navigator.pop(context);
},
windowBody: Padding(
padding:
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
? EdgeInsets.symmetric(horizontal: screenWidth * 0.05)
: EdgeInsets.symmetric(horizontal: screenWidth * 0),
child: Column(
children: [
MihForm(
formKey: _formKey,
formFields: [
MihDropdownField(
controller: _dropdownLinkNameController,
hintText: 'Site Name',
dropdownOptions: _dropdowOptions,
requiredText: true,
editable: true,
enableSearch: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
onSelected: (value) {
setState(() {});
},
),
const SizedBox(height: 10),
MihTextFormField(
fillColor: MihColors.secondary(),
inputColor: MihColors.primary(),
controller: _linkNameController,
hintText: "Custom Name",
requiredText: isOtherSelected,
validator: (value) {
if (isOtherSelected) {
return MihValidationServices().isEmpty(value);
}
return null;
},
),
const SizedBox(height: 10),
MihTextFormField(
fillColor: MihColors.secondary(),
inputColor: MihColors.primary(),
controller: _destinationController,
hintText: "Link",
requiredText: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 20),
MihButton(
onPressed: () async {
if (_formKey.currentState!.validate()) {
MihProfileLinksServices.loadingPopUp(context);
int statusCode =
await MihProfileLinksServices.updateProfileLink(
profileProvider,
widget.link.idprofile_links,
profileProvider.user!.app_id,
"",
_dropdownLinkNameController.text,
_linkNameController.text,
_destinationController.text,
widget.link.order,
context,
);
context.pop();
if (statusCode == 200) {
context.pop();
successPopUp(
"Profile Link Updated",
"You have successfully update a link in your profile",
0);
} else {
MihAlertServices().internetConnectionAlert(context);
}
} else {
MihAlertServices().inputErrorAlert(context);
}
},
buttonColor: MihColors.green(),
width: 300,
child: Text(
"Update",
style: TextStyle(
color: MihColors.primary(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
),
],
),
),
);
},
);
}
}
@@ -0,0 +1,226 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/mih_objects/profile_link.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/components/mih_edit_user_profile_links_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_profile_links_service.dart';
import 'package:provider/provider.dart';
class MihManageUserProfileLinksWindow extends StatefulWidget {
const MihManageUserProfileLinksWindow({super.key});
@override
State<MihManageUserProfileLinksWindow> createState() =>
_MihManageUserProfileLinksWindowState();
}
class _MihManageUserProfileLinksWindowState
extends State<MihManageUserProfileLinksWindow> {
void successPopUp(String title, String message, int packageIndex) {
MihAlertServices().successBasicAlert(
title,
message,
context,
);
}
void removeLinkWarning(
MzansiProfileProvider profileProvider, int idprofile_links) {
MihAlertServices().warningAdvancedAlert(
"Remove Link?",
"Are you sure you want to remove this link from your profile?",
[
MihButton(
onPressed: () async {
MihProfileLinksServices.loadingPopUp(context);
int statusCode = await MihProfileLinksServices.deleteProfileLink(
profileProvider,
idprofile_links,
);
context.pop();
context.pop();
if (statusCode == 200) {
successPopUp("profile Link Deleted",
"you have successfully deleted a link to your profile", 0);
} else {
MihAlertServices().internetConnectionAlert(context);
}
},
buttonColor: MihColors.red(),
width: 300,
child: Text(
"Remove",
style: TextStyle(
color: MihColors.primary(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
MihButton(
onPressed: () async {
context.pop();
},
buttonColor: MihColors.green(),
width: 300,
child: Text(
"Cancel",
style: TextStyle(
color: MihColors.primary(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
context,
);
}
void editLinkWindow(ProfileLink link) {
showDialog(
context: context,
builder: (context) => MihEditUserProfileLinksWindow(link: link));
}
Widget linkActions(MzansiProfileProvider profileProvider, ProfileLink link) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
color: MihColors.green(),
onPressed: () {
editLinkWindow(link);
},
icon: Icon(
Icons.edit,
),
),
const SizedBox(width: 2),
IconButton(
color: MihColors.red(),
onPressed: () {
removeLinkWarning(profileProvider, link.idprofile_links);
},
icon: Icon(
Icons.delete,
),
),
],
);
}
@override
Widget build(BuildContext context) {
// double screenWidth = MediaQuery.of(context).size.width;
return Consumer<MzansiProfileProvider>(
builder: (
BuildContext context,
MzansiProfileProvider profileProvider,
Widget? child,
) {
// return Placeholder();
return MihPackageWindow(
fullscreen: true,
windowTitle: "Manage Links",
onWindowTapClose: () {
Navigator.pop(context);
},
windowBody: Column(
children: [
Expanded(
child: Theme(
data: Theme.of(context).copyWith(
iconTheme: IconThemeData(
color: MihColors.grey(),
),
),
child: ReorderableListView.builder(
itemBuilder: (context, index) {
ProfileLink link = profileProvider.personalLinks[index];
String display = link.site_name;
if (link.custom_name.isNotEmpty) {
display += " (${link.custom_name})";
}
return ListTile(
key: ValueKey("$index"),
title: Text(
"$display",
style: TextStyle(
// fontWeight: FontWeight.bold,
fontSize: 18,
),
),
leading: linkActions(
profileProvider,
link,
),
);
},
itemCount: profileProvider.personalLinks.length,
onReorder: (oldIndex, newIndex) {
if (oldIndex < newIndex) {
newIndex -= 1;
}
final ProfileLink link =
profileProvider.personalLinks.removeAt(oldIndex);
profileProvider.personalLinks.insert(newIndex, link);
}),
),
),
MihButton(
onPressed: () async {
MihProfileLinksServices.loadingPopUp(context);
int newIndex = 1;
for (var link in profileProvider.personalLinks) {
int statusCode =
await MihProfileLinksServices.updateProfileLink(
profileProvider,
link.idprofile_links,
link.app_id,
link.business_id,
link.site_name,
link.custom_name,
link.destination,
newIndex,
context);
if (statusCode != 200) {
await MihProfileLinksServices.updateProfileLink(
profileProvider,
link.idprofile_links,
link.app_id,
link.business_id,
link.site_name,
link.custom_name,
link.destination,
newIndex,
context);
}
newIndex++;
}
context.pop();
context.pop();
successPopUp("profile Link Reordered",
"you have successfully reordered your profile links", 0);
},
buttonColor: MihColors.green(),
width: 300,
child: Text(
"Update Order",
style: TextStyle(
color: MihColors.primary(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 10),
],
),
);
},
);
}
}
@@ -1,10 +1,12 @@
import 'package:go_router/go_router.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_qr_code.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_settings.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_data_helper_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_profile_links_service.dart';
import 'package:provider/provider.dart';
class MzansiProfile extends StatefulWidget {
@@ -19,6 +21,7 @@ class MzansiProfile extends StatefulWidget {
class _MzansiProfileState extends State<MzansiProfile> {
bool _isLoadingInitialData = true;
late final MihPersonalProfile _personalProfile;
late final MihPersonalQrCode _personalQrCode;
late final MihPersonalSettings _personalSettings;
Future<void> _loadInitialData() async {
@@ -32,6 +35,10 @@ class _MzansiProfileState extends State<MzansiProfile> {
mzansiProfileProvider,
);
}
await MihProfileLinksServices.getUserProfileLinks(
mzansiProfileProvider,
mzansiProfileProvider.user!.app_id,
);
setState(() {
_isLoadingInitialData = false;
});
@@ -41,6 +48,7 @@ class _MzansiProfileState extends State<MzansiProfile> {
void initState() {
super.initState();
_personalProfile = const MihPersonalProfile();
_personalQrCode = const MihPersonalQrCode(user: null);
_personalSettings = const MihPersonalSettings();
_loadInitialData();
}
@@ -91,12 +99,12 @@ class _MzansiProfileState extends State<MzansiProfile> {
temp[const Icon(Icons.person)] = () {
context.read<MzansiProfileProvider>().setPersonalIndex(0);
};
// temp[const Icon(Icons.person)] = () {
// context.read<MzansiProfileProvider>().setPersonalIndex(1);
// };
temp[const Icon(Icons.settings)] = () {
temp[const Icon(Icons.qr_code_rounded)] = () {
context.read<MzansiProfileProvider>().setPersonalIndex(1);
};
temp[const Icon(Icons.settings)] = () {
context.read<MzansiProfileProvider>().setPersonalIndex(2);
};
return MihPackageTools(
tools: temp,
selectedIndex: context.watch<MzansiProfileProvider>().personalIndex,
@@ -106,6 +114,7 @@ class _MzansiProfileState extends State<MzansiProfile> {
List<Widget> getToolBody() {
return [
_personalProfile,
_personalQrCode,
_personalSettings,
];
}
@@ -113,6 +122,7 @@ class _MzansiProfileState extends State<MzansiProfile> {
List<String> getToolTitle() {
List<String> toolTitles = [
"Profile",
"Share",
"Settings",
];
return toolTitles;
@@ -1,11 +1,18 @@
import 'package:go_router/go_router.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile_view.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_qr_code.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
import 'package:provider/provider.dart';
class MzansiProfileView extends StatefulWidget {
final String? username;
const MzansiProfileView({
super.key,
required this.username,
});
@override
@@ -15,25 +22,60 @@ class MzansiProfileView extends StatefulWidget {
class _MzansiProfileViewState extends State<MzansiProfileView> {
int _selectedIndex = 0;
late final MihPersonalProfileView _personalProfileView;
late final MihPersonalQrCode _personalQrCode;
void _loadUserData() async {
MzansiDirectoryProvider directoryProvider =
context.read<MzansiDirectoryProvider>();
if (widget.username != null) {
final user = await MihUserServices()
.getMIHUserDetailsByUsername(widget.username!, context);
if (user == null) {
context.goNamed(
'mihHome',
extra: true,
);
} else {
KenLogger.success("User found: ${user.username}");
directoryProvider.setSelectedUser(user: user);
}
}
_personalProfileView = MihPersonalProfileView();
_personalQrCode = MihPersonalQrCode(user: directoryProvider.selectedUser);
}
@override
void initState() {
super.initState();
_personalProfileView = MihPersonalProfileView();
_loadUserData();
}
@override
Widget build(BuildContext context) {
return MihPackage(
packageActionButton: getAction(),
packageTools: getTools(),
packageToolBodies: getToolBody(),
packageToolTitles: getToolTitle(),
selectedBodyIndex: _selectedIndex,
onIndexChange: (newValue) {
setState(() {
_selectedIndex = newValue;
});
return Consumer<MzansiDirectoryProvider>(
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
Widget? child) {
if (directoryProvider.selectedUser == null) {
KenLogger.warning("User is null, showing loading indicator");
return Scaffold(
body: const Center(
child: Mihloadingcircle(),
),
);
} else {
return MihPackage(
packageActionButton: getAction(),
packageTools: getTools(),
packageToolBodies: getToolBody(),
packageToolTitles: getToolTitle(),
selectedBodyIndex: _selectedIndex,
onIndexChange: (newValue) {
setState(() {
_selectedIndex = newValue;
});
},
);
}
},
);
}
@@ -57,6 +99,11 @@ class _MzansiProfileViewState extends State<MzansiProfileView> {
_selectedIndex = 0;
});
};
temp[const Icon(Icons.qr_code_rounded)] = () {
setState(() {
_selectedIndex = 1;
});
};
return MihPackageTools(
tools: temp,
selectedIndex: _selectedIndex,
@@ -66,12 +113,14 @@ class _MzansiProfileViewState extends State<MzansiProfileView> {
List<Widget> getToolBody() {
return [
_personalProfileView,
_personalQrCode,
];
}
List<String> getToolTitle() {
List<String> toolTitles = [
"Profile",
"Share",
];
return toolTitles;
}
@@ -2,9 +2,10 @@ import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.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_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_profile_links.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/components/mih_add_user_profile_links_window.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/components/mih_manage_user_profile_links_window.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/components/mih_edit_personal_profile_window.dart';
import 'package:provider/provider.dart';
@@ -20,107 +21,29 @@ class _MihPersonalProfileState extends State<MihPersonalProfile> {
TextEditingController proPicController = TextEditingController();
PlatformFile? newSelectedProPic;
void editProfileWindow(double width) {
void editProfileWindow() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => Consumer<MzansiProfileProvider>(
builder: (BuildContext context,
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
return MihEditPersonalProfileWindow();
},
),
builder: (context) => MihEditPersonalProfileWindow(),
);
}
List<ProfileLink> getTempLinks() {
// return [];
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",
),
];
void addProfileLinksWindow() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihAddUserProfileLinksWindow(),
);
}
void editProfileLinksWindow() {
showDialog(
context: context,
// barrierDismissible: false,
// builder: (context) => Placeholder(),
builder: (context) => MihManageUserProfileLinksWindow(),
);
}
@override
@@ -176,7 +99,7 @@ class _MihPersonalProfileState extends State<MihPersonalProfile> {
right: 5,
child: MihButton(
onPressed: () {
editProfileWindow(width);
editProfileWindow();
},
buttonColor: MihColors.green(),
width: 35,
@@ -245,20 +168,20 @@ class _MihPersonalProfileState extends State<MihPersonalProfile> {
),
const SizedBox(height: 15.0),
MihProfileLinks(
// links: mzansiProfileProvider.personalLinks,
links: getTempLinks(),
links: mzansiProfileProvider.personalLinks,
),
const SizedBox(height: 5.0),
const SizedBox(height: 8.0),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MihButton(
onPressed: () {
editProfileWindow(width);
addProfileLinksWindow();
},
buttonColor: MihColors.green(),
// width: mzansiProfileProvider.personalLinks.isNotEmpty ? 50 : null,
width: getTempLinks().isNotEmpty ? 50 : null,
width: mzansiProfileProvider.personalLinks.isNotEmpty
? 50
: null,
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
@@ -268,8 +191,7 @@ class _MihPersonalProfileState extends State<MihPersonalProfile> {
Icons.add,
color: MihColors.primary(),
),
// if (mzansiProfileProvider.personalLinks.isEmpty)
if (getTempLinks().isEmpty)
if (mzansiProfileProvider.personalLinks.isEmpty)
Text(
"Add Links",
style: TextStyle(
@@ -281,6 +203,19 @@ class _MihPersonalProfileState extends State<MihPersonalProfile> {
],
),
),
const SizedBox(width: 8.0),
MihButton(
onPressed: () {
editProfileLinksWindow();
},
buttonColor: MihColors.green(),
width: 50,
height: 50,
child: Icon(
Icons.edit,
color: MihColors.primary(),
),
),
],
),
const SizedBox(height: 20.0),
@@ -1,12 +1,20 @@
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/foundation.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.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_banner_ad.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_profile_links.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_profile_links_service.dart';
import 'package:provider/provider.dart';
import 'package:redacted/redacted.dart';
class MihPersonalProfileView extends StatefulWidget {
const MihPersonalProfileView({
@@ -19,6 +27,7 @@ class MihPersonalProfileView extends StatefulWidget {
class _MihPersonalProfileViewState extends State<MihPersonalProfileView> {
late Future<String> futureImageUrl;
late Future<List<ProfileLink>> futureLinks;
PlatformFile? file;
@override
@@ -33,6 +42,8 @@ class _MihPersonalProfileViewState extends State<MihPersonalProfileView> {
context.read<MzansiDirectoryProvider>();
futureImageUrl = MihFileApi.getMinioFileUrl(
directoryProvider.selectedUser!.pro_pic_path);
futureLinks = MihProfileLinksServices.getUserProfileLinksMD(
directoryProvider, directoryProvider.selectedUser!.app_id);
}
@override
@@ -51,105 +62,153 @@ class _MihPersonalProfileViewState extends State<MihPersonalProfileView> {
return Consumer<MzansiDirectoryProvider>(
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
Widget? child) {
return MihSingleChildScroll(
scrollbarOn: true,
child: Padding(
padding:
MzansiInnovationHub.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: CachedNetworkImageProvider(
asyncSnapshot.requireData),
width: profilePictureWidth,
expandable: true,
editable: false,
fileNameController: TextEditingController(),
userSelectedfile: file,
frameColor: MihColors.secondary(),
backgroundColor: MihColors.primary(),
onChange: () {},
);
} else {
return Icon(
MihIcons.iDontKnow,
size: profilePictureWidth,
return Column(
children: [
Expanded(
child: MihSingleChildScroll(
scrollbarOn: true,
child: Padding(
padding: MzansiInnovationHub.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: CachedNetworkImageProvider(
asyncSnapshot.requireData),
width: profilePictureWidth,
expandable: true,
editable: false,
fileNameController: TextEditingController(),
userSelectedfile: file,
frameColor: MihColors.secondary(),
backgroundColor: MihColors.primary(),
onChange: () {},
);
} else {
return Icon(
MihIcons.iDontKnow,
size: profilePictureWidth,
color: MihColors.secondary(),
);
}
} else {
return Icon(
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.secondary(),
);
}
}),
FittedBox(
child: Text(
directoryProvider.selectedUser!.username.isNotEmpty
? directoryProvider.selectedUser!.username
: "Username",
style: TextStyle(
fontSize: 35,
fontWeight: FontWeight.bold,
color: MihColors.secondary(),
);
}
} else {
return Icon(
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.secondary(),
);
}
}),
FittedBox(
child: Text(
directoryProvider.selectedUser!.username.isNotEmpty
? directoryProvider.selectedUser!.username
: "Username",
style: TextStyle(
fontSize: 35,
fontWeight: FontWeight.bold,
color: MihColors.secondary(),
),
),
),
FittedBox(
child: Text(
directoryProvider.selectedUser!.fname.isNotEmpty
? "${directoryProvider.selectedUser!.fname} ${directoryProvider.selectedUser!.lname}"
: "Name Surname",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.secondary(),
),
),
),
FittedBox(
child: Text(
directoryProvider.selectedUser!.type.toUpperCase(),
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: MihColors.secondary(),
),
),
),
const SizedBox(height: 10.0),
Center(
child: SizedBox(
width: 700,
child: Text(
directoryProvider.selectedUser!.purpose.isNotEmpty
? directoryProvider.selectedUser!.purpose
: "No Personal Mission added yet",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: MihColors.secondary(),
),
),
),
),
FittedBox(
child: Text(
directoryProvider.selectedUser!.fname.isNotEmpty
? "${directoryProvider.selectedUser!.fname} ${directoryProvider.selectedUser!.lname}"
: "Name Surname",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: MihColors.secondary(),
),
),
),
FittedBox(
child: Text(
directoryProvider.selectedUser!.type.toUpperCase(),
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: MihColors.secondary(),
),
),
),
const SizedBox(height: 10.0),
Center(
child: SizedBox(
width: 700,
child: Text(
directoryProvider.selectedUser!.purpose.isNotEmpty
? directoryProvider.selectedUser!.purpose
: "No Personal Mission added yet",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: MihColors.secondary(),
),
),
),
),
const SizedBox(height: 15.0),
FutureBuilder(
future: futureLinks,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState ==
ConnectionState.done &&
asyncSnapshot.hasData) {
directoryProvider.setPersonalLinks(
personalLinks: asyncSnapshot.data!);
return MihProfileLinks(
links: directoryProvider.personalLinks,
);
} else {
return Wrap(
alignment: WrapAlignment.center,
runAlignment: WrapAlignment.center,
runSpacing: 10,
spacing: 10,
children: [
Container(width: 70, height: 70).redacted(
context: context,
redact: true,
),
Container(width: 70, height: 70).redacted(
context: context,
redact: true,
),
Container(width: 70, height: 70).redacted(
context: context,
redact: true,
),
Container(width: 70, height: 70).redacted(
context: context,
redact: true,
),
],
);
}
}),
],
),
),
const SizedBox(height: 30.0),
],
),
),
),
!kIsWeb && (Platform.isAndroid || Platform.isIOS)
? MihBannerAd()
: SizedBox(),
SizedBox(height: 10),
],
);
},
);
@@ -0,0 +1,410 @@
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:file_picker/file_picker.dart';
import 'package:file_saver/file_saver.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:go_router/go_router.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
import 'package:provider/provider.dart';
import 'package:screenshot/screenshot.dart';
import 'package:share_plus/share_plus.dart';
import 'package:supertokens_flutter/supertokens.dart';
class MihPersonalQrCode extends StatefulWidget {
final AppUser? user;
const MihPersonalQrCode({
super.key,
required this.user,
});
@override
State<MihPersonalQrCode> createState() => _MihPersonalQrCodeState();
}
class _MihPersonalQrCodeState extends State<MihPersonalQrCode> {
late AppUser user;
late Future<String> futureImageUrl;
PlatformFile? file;
int qrSize = 500;
ScreenshotController screenshotController = ScreenshotController();
Uint8List? personalQRImageFile;
bool _isUserSignedIn = false;
final String _qrCodedata =
"${AppEnviroment.baseAppUrl}/mzansi-profile/view?username=";
Future<void> _checkUserSession() async {
final doesSessionExist = await SuperTokens.doesSessionExist();
setState(() {
_isUserSignedIn = doesSessionExist;
});
}
String getQrCodeData(int qrSize) {
String color =
MihColors.primary().toARGB32().toRadixString(16).substring(2, 8);
// KenLogger.warning(color);
String bgColor =
MihColors.secondary().toARGB32().toRadixString(16).substring(2, 8);
// KenLogger.warning(bgColor);
String encodedData = Uri.encodeComponent("$_qrCodedata${user.username}");
return "https://api.qrserver.com/v1/create-qr-code/?data=$encodedData&size=${qrSize}x$qrSize&bgcolor=$bgColor&color=$color";
}
Future<void> saveImage(Uint8List imageBytes) async {
final String filename =
"${user.username}_QR_Code_${DateTime.now().millisecondsSinceEpoch}";
// "${user.username}_QR_Code_${DateTime.now().millisecondsSinceEpoch}.png";
if (kIsWeb) {
await FileSaver.instance.saveFile(
name: filename,
bytes: imageBytes,
fileExtension: "png",
mimeType: MimeType.png,
);
} else if (defaultTargetPlatform == TargetPlatform.linux ||
defaultTargetPlatform == TargetPlatform.windows) {
// Use File Picker to get a save path on Desktop
String? outputFile = await FilePicker.platform.saveFile(
dialogTitle: 'Please select where to save your QR Code:',
fileName: filename,
);
if (outputFile != null) {
final file = File(outputFile);
await file.writeAsBytes(imageBytes);
KenLogger.success("Saved to $outputFile");
}
} else {
await FileSaver.instance.saveAs(
name: filename,
bytes: imageBytes,
fileExtension: "png",
mimeType: MimeType.png,
);
}
}
Future<void> downloadQrCode() async {
if (_isUserSignedIn) {
await screenshotController.capture().then((image) {
// KenLogger.success("Image Captured: $image");
setState(() {
personalQRImageFile = image;
});
}).catchError((onError) {
KenLogger.error(onError);
});
// KenLogger.success("QR Code Image Captured : $businessQRImageFile");
saveImage(personalQRImageFile!);
} else {
showSignInRequiredAlert();
}
}
void showSignInRequiredAlert() {
showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return MihPackageWindow(
fullscreen: false,
windowTitle: null,
onWindowTapClose: null,
windowBody: Column(
children: [
Icon(
MihIcons.mihLogo,
size: 100,
color: MihColors.secondary(),
),
Text(
"Let's Get Started",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.primary(),
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.secondary(),
fontSize: 15,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.goNamed(
'mihHome',
extra: true,
);
},
buttonColor: MihColors.green(),
elevation: 10,
width: 300,
child: Text(
"Sign In/ Create Account",
style: TextStyle(
color: MihColors.primary(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
);
},
);
}
Widget displayPersonalQRCode(double profilePictureWidth) {
return Screenshot(
controller: screenshotController,
child: Material(
color: MihColors.secondary().withValues(alpha: 0.6),
borderRadius: BorderRadius.circular(25),
elevation: 10,
shadowColor: Colors.black,
child: Container(
decoration: BoxDecoration(
color: MihColors.secondary(),
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 != "" ||
asyncSnapshot.requireData.isNotEmpty) {
return MihCircleAvatar(
imageFile: CachedNetworkImageProvider(
asyncSnapshot.requireData),
width: profilePictureWidth,
expandable: true,
editable: false,
fileNameController: TextEditingController(),
userSelectedfile: file,
frameColor: MihColors.primary(),
backgroundColor: MihColors.secondary(),
onChange: () {},
);
} else {
return Icon(
MihIcons.iDontKnow,
size: profilePictureWidth,
color: MihColors.primary(),
);
}
} else {
return Icon(
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.primary(),
);
}
},
),
FittedBox(
child: Text(
user.username,
style: TextStyle(
fontSize: 35,
fontWeight: FontWeight.bold,
color: MihColors.primary(),
),
),
),
FittedBox(
child: Text(
"${user.fname} ${user.lname}",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
color: MihColors.primary(),
),
),
),
const SizedBox(height: 5),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FittedBox(
child: Text(
"Powered by MIH",
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w600,
color: MihColors.primary(),
),
),
),
const SizedBox(width: 5),
Icon(
MihIcons.mihLogo,
size: 20,
color: MihColors.primary(),
),
],
),
const SizedBox(height: 10),
SizedBox(
width: 300,
height: 300,
child: CachedNetworkImage(
imageUrl: getQrCodeData(qrSize.toInt()),
placeholder: (context, url) => FittedBox(
child: 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.primary(),
),
),
),
],
)),
),
),
);
}
void shareMIHLink(BuildContext context, String message, String link) {
String shareText = "$message: $link";
SharePlus.instance.share(
ShareParams(text: shareText),
);
}
@override
void initState() {
super.initState();
MzansiProfileProvider profileProvider =
context.read<MzansiProfileProvider>();
if (widget.user != null) {
user = widget.user!;
} else {
user = profileProvider.user!;
}
_checkUserSession();
futureImageUrl = MihFileApi.getMinioFileUrl(user.pro_pic_path);
}
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
return Consumer(builder: (
BuildContext context,
MzansiDirectoryProvider directoryProvider,
Widget? child,
) {
return MihPackageToolBody(
backgroundColor: MihColors.primary(),
borderOn: false,
innerHorizontalPadding: 10,
bodyItem: getBody(screenSize, context),
);
});
}
Widget getBody(Size screenSize, BuildContext context) {
double profilePictureWidth = 150;
return Stack(
alignment: Alignment.topCenter,
children: [
MihSingleChildScroll(
scrollbarOn: true,
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: displayPersonalQRCode(profilePictureWidth),
),
),
),
),
Positioned(
right: 10,
bottom: 10,
child: MihFloatingMenu(
animatedIcon: AnimatedIcons.menu_close,
children: [
SpeedDialChild(
child: Icon(
Icons.download_rounded,
color: MihColors.primary(),
),
label: "Download QR Code",
labelBackgroundColor: MihColors.green(),
labelStyle: TextStyle(
color: MihColors.primary(),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.green(),
onTap: () {
downloadQrCode();
},
),
SpeedDialChild(
child: Icon(
Icons.share_rounded,
color: MihColors.primary(),
),
label: "Share Profile",
labelBackgroundColor: MihColors.green(),
labelStyle: TextStyle(
color: MihColors.primary(),
fontWeight: FontWeight.bold,
),
backgroundColor: MihColors.green(),
onTap: () {
shareMIHLink(
context,
"Check out ${user.username} on the MIH app's Mzansi Directory",
"$_qrCodedata${user.username}",
);
},
),
]),
)
],
);
}
}