rename container folders
This commit is contained in:
102
mih_ui/lib/mih_packages/about_mih/about_mih.dart
Normal file
102
mih_ui/lib/mih_packages/about_mih/about_mih.dart
Normal file
@@ -0,0 +1,102 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/about_mih_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tools/mih_%20attributes.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tools/mih_info.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tools/mih_privacy_policy.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tools/mih_terms_of_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class AboutMih extends StatefulWidget {
|
||||
const AboutMih({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AboutMih> createState() => _AboutMihState();
|
||||
}
|
||||
|
||||
class _AboutMihState extends State<AboutMih> {
|
||||
late final MihInfo _info;
|
||||
late final MihPrivacyPolicy _privacyPolicy;
|
||||
late final MIHTermsOfService _termsOfService;
|
||||
late final MihAttributes _attributes;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_info = MihInfo();
|
||||
_privacyPolicy = MihPrivacyPolicy();
|
||||
_termsOfService = MIHTermsOfService();
|
||||
_attributes = MihAttributes();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: context.watch<AboutMihProvider>().toolIndex,
|
||||
onIndexChange: (newIndex) {
|
||||
context.read<AboutMihProvider>().setToolIndex(newIndex);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.info)] = () {
|
||||
context.read<AboutMihProvider>().setToolIndex(0);
|
||||
};
|
||||
temp[const Icon(Icons.policy)] = () {
|
||||
context.read<AboutMihProvider>().setToolIndex(1);
|
||||
};
|
||||
temp[const Icon(Icons.design_services)] = () {
|
||||
context.read<AboutMihProvider>().setToolIndex(2);
|
||||
};
|
||||
temp[const Icon(Icons.star_rounded)] = () {
|
||||
context.read<AboutMihProvider>().setToolIndex(3);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<AboutMihProvider>().toolIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_info,
|
||||
_privacyPolicy,
|
||||
_termsOfService,
|
||||
_attributes,
|
||||
];
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"About",
|
||||
"Privacy Policy",
|
||||
"Terms of Service",
|
||||
"Attributions",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,44 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tile.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class AboutMihTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
const AboutMihTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AboutMihTile> createState() => _AboutMihTileState();
|
||||
}
|
||||
|
||||
class _AboutMihTileState extends State<AboutMihTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageTile(
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
"aboutMih",
|
||||
);
|
||||
// Navigator.of(context).pushNamed(
|
||||
// '/about',
|
||||
// arguments: 0,
|
||||
// );
|
||||
},
|
||||
appName: "About MIH",
|
||||
appIcon: Icon(
|
||||
MihIcons.aboutMih,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: widget.packageSize,
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class MihAttributes extends StatefulWidget {
|
||||
const MihAttributes({super.key});
|
||||
|
||||
@override
|
||||
State<MihAttributes> createState() => _MihAttributesState();
|
||||
}
|
||||
|
||||
class _MihAttributesState extends State<MihAttributes> {
|
||||
Future<void> launchUrlLink(Uri linkUrl) async {
|
||||
if (!await launchUrl(linkUrl)) {
|
||||
throw Exception('Could not launch $linkUrl');
|
||||
}
|
||||
}
|
||||
|
||||
TableRow displayIcon(IconData icon, String creator, String link) {
|
||||
return TableRow(
|
||||
children: [
|
||||
TableCell(
|
||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
||||
child: SizedBox(
|
||||
height: 150,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15.0),
|
||||
child: FittedBox(
|
||||
child: Center(
|
||||
child: Icon(
|
||||
icon,
|
||||
// size: 125,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
TableCell(
|
||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: Center(
|
||||
child: Text(
|
||||
creator,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
TableCell(
|
||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15.0),
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
launchUrlLink(
|
||||
Uri.parse(
|
||||
link,
|
||||
),
|
||||
);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 100,
|
||||
child: Text(
|
||||
"Visit",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody() {
|
||||
String message =
|
||||
"Some APIs, Icons and Assets used in MIH were sourced from third party providers.\n";
|
||||
message +=
|
||||
"We are grateful to the talented creators for providing these resources.\n";
|
||||
message +=
|
||||
"As per the terms for free use for these third party providers, the following assets require attribution";
|
||||
|
||||
return MihSingleChildScroll(
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(
|
||||
MihIcons.mihLogo,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
size: 165,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
SelectableText(
|
||||
message,
|
||||
style: const TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: Table(
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||
columnWidths: const {
|
||||
0: FlexColumnWidth(1),
|
||||
1: FlexColumnWidth(1),
|
||||
2: FlexColumnWidth(1),
|
||||
},
|
||||
children: [
|
||||
const TableRow(
|
||||
children: [
|
||||
TableCell(
|
||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15.0),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Resources",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
TableCell(
|
||||
verticalAlignment: TableCellVerticalAlignment.middle,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15.0),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Creator",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15.0),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Link",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
displayIcon(MihIcons.mihRing, "Tarah Meth",
|
||||
"https://www.linkedin.com/in/tarah-meth-3b6309254/"),
|
||||
displayIcon(MihIcons.mihLogo, "Tarah Meth",
|
||||
"https://www.linkedin.com/in/tarah-meth-3b6309254/"),
|
||||
displayIcon(MihIcons.mzansiAi, "Ollama", "https://ollama.com/"),
|
||||
displayIcon(MihIcons.mzansiWallet, "Freepik",
|
||||
"https://www.flaticon.com/free-icon/wallet-passes-app_3884407?term=wallet&page=1&position=21&origin=search&related_id=3884407"),
|
||||
displayIcon(MihIcons.patientProfile, "RaftelDesign",
|
||||
"https://www.flaticon.com/free-icon/patient_2376100?term=medication&page=1&position=6&origin=search&related_id=2376100"),
|
||||
displayIcon(MihIcons.patientProfile, "Srip",
|
||||
"https://www.flaticon.com/free-icon/hospital_1233930?term=medical+snake&page=1&position=7&origin=search&related_id=1233930"),
|
||||
displayIcon(MihIcons.calendar, "Freepik",
|
||||
"https://www.flaticon.com/free-icon/calendar_2278049?term=calendar&page=1&position=5&origin=search&related_id=2278049"),
|
||||
displayIcon(MihIcons.calculator, "Freepik",
|
||||
"https://www.flaticon.com/free-icon/calculator_2374409?term=calculator&page=1&position=20&origin=search&related_id=2374409"),
|
||||
displayIcon(MihIcons.aboutMih, "Chanut",
|
||||
"https://www.flaticon.com/free-icon/info_151776?term=about&page=1&position=8&origin=search&related_id=151776"),
|
||||
displayIcon(MihIcons.personalProfile, "Freepik",
|
||||
"https://www.flaticon.com/free-icon/user_1077063?term=profile&page=1&position=6&origin=search&related_id=1077063"),
|
||||
displayIcon(MihIcons.businessProfile, "Gravisio",
|
||||
"https://www.flaticon.com/free-icon/contractor_11813336?term=company+profile&page=1&position=2&origin=search&related_id=11813336"),
|
||||
displayIcon(MihIcons.patientManager, "Vector Tank",
|
||||
"https://www.flaticon.com/free-icon/doctor_10215061?term=doctor&page=1&position=73&origin=search&related_id=10215061"),
|
||||
displayIcon(MihIcons.profileSetup, "Freepik",
|
||||
"https://www.flaticon.com/free-icon/add-user_748137?term=profile+add&page=1&position=1&origin=search&related_id=748137"),
|
||||
displayIcon(MihIcons.businessSetup, "kerismaker",
|
||||
"https://www.flaticon.com/free-icon/business_13569850?term=company+add&page=1&position=25&origin=search&related_id=13569850"),
|
||||
displayIcon(MihIcons.calculator, "fawazahmed0",
|
||||
"https://github.com/fawazahmed0/exchange-api"),
|
||||
displayIcon(MihIcons.iDontKnow, "Freepik",
|
||||
"https://www.flaticon.com/free-icon/i-dont-know_5359909?term=i+dont+know&page=1&position=7&origin=search&related_id=5359909"),
|
||||
],
|
||||
),
|
||||
),
|
||||
// SizedBox(
|
||||
// width: 500,
|
||||
// child: Column(
|
||||
// children: [
|
||||
// const SizedBox(
|
||||
// width: double.infinity,
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
// mainAxisSize: MainAxisSize.max,
|
||||
// children: [
|
||||
// Flexible(
|
||||
// child: Text(
|
||||
// "Icon",
|
||||
// style: TextStyle(
|
||||
// fontSize: 25,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Flexible(
|
||||
// child: Text(
|
||||
// "Creator",
|
||||
// style: TextStyle(
|
||||
// fontSize: 25,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Flexible(
|
||||
// child: Text(
|
||||
// "Link",
|
||||
// style: TextStyle(
|
||||
// fontSize: 25,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// const Padding(
|
||||
// padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||
// child: Divider(),
|
||||
// ),
|
||||
// displayIcon(MihIcons.mihLogo, "Tarah Meth",
|
||||
// "https://app.mzansi-innovation-hub.co.za/"),
|
||||
// const SizedBox(height: 10),
|
||||
// displayIcon(MihIcons.mihLogo, "Test",
|
||||
// "https://www.flaticon.com/free-icons/mih"),
|
||||
// const SizedBox(height: 10),
|
||||
// displayIcon(MihIcons.mihLogo, "Test",
|
||||
// "https://www.flaticon.com/free-icons/mih"),
|
||||
// const SizedBox(height: 10),
|
||||
// displayIcon(MihIcons.mihLogo, "Test",
|
||||
// "https://www.flaticon.com/free-icons/mih"),
|
||||
// const SizedBox(height: 10),
|
||||
// ],
|
||||
// ),
|
||||
// )
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
904
mih_ui/lib/mih_packages/about_mih/package_tools/mih_info.dart
Normal file
904
mih_ui/lib/mih_packages/about_mih/package_tools/mih_info.dart
Normal file
@@ -0,0 +1,904 @@
|
||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||
import 'package:mzansi_innovation_hub/main.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';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_floating_menu.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:redacted/redacted.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
class MihInfo extends StatefulWidget {
|
||||
const MihInfo({super.key});
|
||||
|
||||
@override
|
||||
State<MihInfo> createState() => _MihInfoState();
|
||||
}
|
||||
|
||||
class _MihInfoState extends State<MihInfo> {
|
||||
late Future<int> _futureUserCount;
|
||||
late Future<int> _futureBusinessCount;
|
||||
|
||||
Widget founderBio() {
|
||||
String bio = "";
|
||||
bio += "BSc Computer Science & Information Systems\n";
|
||||
bio += "(University of the Western Cape)\n";
|
||||
bio +=
|
||||
"6 Year of banking experience with one of the big 5 banks of South Africa.";
|
||||
return Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 300,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
fit: StackFit.loose,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 4.0),
|
||||
child: CircleAvatar(
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
backgroundImage: const AssetImage(
|
||||
"lib/mih_package_components/assets/images/founder.jpg"),
|
||||
//'https://media.licdn.com/dms/image/D4D03AQGd1-QhjtWWpA/profile-displayphoto-shrink_400_400/0/1671698053061?e=2147483647&v=beta&t=a3dJI5yxs5-KeXjj10LcNCFuC9IOfa8nNn3k_Qyr0CA'),
|
||||
radius: 75,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
MihIcons.mihRing,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 400,
|
||||
child: Text(
|
||||
bio,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
//fontWeight: FontWeight.bold,
|
||||
fontSize: 17,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget founderTitle() {
|
||||
String heading = "Yasien Meth (Founder & CEO)";
|
||||
return Column(
|
||||
children: [
|
||||
Text(
|
||||
heading,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget ourVision() {
|
||||
String heading = "Our Vision";
|
||||
String vision =
|
||||
"Digitizing Mzansi one process at a time. Discover essential Mzansi apps to streamline your personal and professional life. Simplify your daily tasks with our user-friendly solutions.";
|
||||
|
||||
return SizedBox(
|
||||
width: 500,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text(
|
||||
heading,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Text(
|
||||
vision,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
//fontWeight: FontWeight.bold,
|
||||
fontSize: 17,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget ourMission() {
|
||||
String heading = "Our Mission";
|
||||
String mission =
|
||||
"Bridge the digital divide in Mzansi, ensuring that everyone can benefit from the power of technology. We empower lives by providing simple, elegant solutions that elevate daily experiences. With our user-friendly approach, we're making the digital world accessible to all, ensuring no one is left behind in the digital revolution.";
|
||||
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,
|
||||
),
|
||||
Text(
|
||||
mission,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
//fontWeight: FontWeight.bold,
|
||||
fontSize: 17,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> launchSocialUrl(Uri linkUrl) async {
|
||||
if (!await launchUrl(linkUrl)) {
|
||||
throw Exception('Could not launch $linkUrl');
|
||||
}
|
||||
}
|
||||
|
||||
Widget getInstallButtonText() {
|
||||
final isWebAndroid =
|
||||
kIsWeb && (defaultTargetPlatform == TargetPlatform.android);
|
||||
final isWebIos = kIsWeb && (defaultTargetPlatform == TargetPlatform.iOS);
|
||||
String btnText = "";
|
||||
IconData platformIcon;
|
||||
if (isWebAndroid) {
|
||||
btnText = "Install MIH";
|
||||
platformIcon = FontAwesomeIcons.googlePlay;
|
||||
} else if (isWebIos) {
|
||||
btnText = "Install MIH";
|
||||
platformIcon = FontAwesomeIcons.appStoreIos;
|
||||
} else if (MzansiInnovationHub.of(context)!.theme.getPlatform() ==
|
||||
"Android") {
|
||||
btnText = "Update MIH";
|
||||
platformIcon = FontAwesomeIcons.googlePlay;
|
||||
} else if (MzansiInnovationHub.of(context)!.theme.getPlatform() == "iOS") {
|
||||
btnText = "Update MIH";
|
||||
platformIcon = FontAwesomeIcons.appStoreIos;
|
||||
} else {
|
||||
btnText = "Install MIH";
|
||||
platformIcon = FontAwesomeIcons.globe;
|
||||
}
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
FaIcon(
|
||||
platformIcon,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
btnText,
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void shareMIHLink(BuildContext context, String message, String link) {
|
||||
String shareText = "$message: $link";
|
||||
SharePlus.instance.share(
|
||||
ShareParams(text: shareText),
|
||||
);
|
||||
}
|
||||
|
||||
Widget displayBusinessCount() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
FutureBuilder<int>(
|
||||
future: _futureBusinessCount,
|
||||
builder: (context, snapshot) {
|
||||
bool isLoading = true;
|
||||
String userCount = "⚠️";
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
isLoading = true;
|
||||
} else if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.hasError) {
|
||||
isLoading = false;
|
||||
} else if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.hasData) {
|
||||
isLoading = false;
|
||||
userCount = snapshot.data.toString();
|
||||
} else {
|
||||
isLoading = true;
|
||||
}
|
||||
return SizedBox(
|
||||
child: Text(
|
||||
userCount,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 23,
|
||||
),
|
||||
),
|
||||
).redacted(
|
||||
context: context,
|
||||
redact: isLoading,
|
||||
configuration: RedactedConfiguration(
|
||||
defaultBorderRadius: BorderRadius.circular(5),
|
||||
redactedColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
"Businesses",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget displayUserCount() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
FutureBuilder<int>(
|
||||
future: _futureUserCount,
|
||||
builder: (context, snapshot) {
|
||||
bool isLoading = true;
|
||||
String userCount = "⚠️";
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
isLoading = true;
|
||||
} else if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.hasError) {
|
||||
isLoading = false;
|
||||
} else if (snapshot.connectionState == ConnectionState.done &&
|
||||
snapshot.hasData) {
|
||||
isLoading = false;
|
||||
userCount = snapshot.data.toString();
|
||||
} else {
|
||||
isLoading = true;
|
||||
}
|
||||
return SizedBox(
|
||||
child: Text(
|
||||
userCount,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 23,
|
||||
),
|
||||
),
|
||||
).redacted(
|
||||
context: context,
|
||||
redact: isLoading,
|
||||
configuration: RedactedConfiguration(
|
||||
defaultBorderRadius: BorderRadius.circular(5),
|
||||
redactedColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Text(
|
||||
"People",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
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<ProfileLink> 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();
|
||||
_futureUserCount = MihUserServices().fetchUserCount();
|
||||
_futureBusinessCount = MihBusinessDetailsServices().fetchBusinessCount();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody() {
|
||||
return Stack(
|
||||
children: [
|
||||
MihSingleChildScroll(
|
||||
child: Column(
|
||||
children: [
|
||||
aboutHeadings(),
|
||||
communityCounter(),
|
||||
callToActionsButtons(),
|
||||
mihDivider(),
|
||||
womenForChange(),
|
||||
mihDivider(),
|
||||
missionAndVission(),
|
||||
mihDivider(),
|
||||
founderDetails(),
|
||||
mihDivider(),
|
||||
mihSocials(),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 10,
|
||||
bottom: 10,
|
||||
child: MihFloatingMenu(
|
||||
icon: Icons.share,
|
||||
children: [
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.android,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Android",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
shareMIHLink(
|
||||
context,
|
||||
"Check out the MIH app on the Play Store",
|
||||
"https://play.google.com/store/apps/details?id=za.co.mzansiinnovationhub.mih",
|
||||
);
|
||||
},
|
||||
),
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.apple,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "iOS",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
shareMIHLink(
|
||||
context,
|
||||
"Check out the MIH app on the App Store",
|
||||
"https://apps.apple.com/za/app/mzansi-innovation-hub/id6743310890",
|
||||
);
|
||||
},
|
||||
),
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.store,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Huawei",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
shareMIHLink(
|
||||
context,
|
||||
"Check out the MIH app on the App Gallery",
|
||||
"https://appgallery.huawei.com/app/C113315335?pkgName=za.co.mzansiinnovationhub.mih",
|
||||
);
|
||||
},
|
||||
),
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.vpn_lock,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Web",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
shareMIHLink(
|
||||
context,
|
||||
"Check out the MIH app on the Web",
|
||||
"https://app.mzansi-innovation-hub.co.za/",
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/about_mih/mih_policy_tos_ext/policy_and_terms_text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MihPrivacyPolicy extends StatefulWidget {
|
||||
const MihPrivacyPolicy({super.key});
|
||||
|
||||
@override
|
||||
State<MihPrivacyPolicy> createState() => _MihPrivacyPolicyState();
|
||||
}
|
||||
|
||||
class _MihPrivacyPolicyState extends State<MihPrivacyPolicy> {
|
||||
bool englishOn = true;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(context),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(BuildContext context) {
|
||||
List<Widget> children = [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
englishOn = !englishOn;
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
child: Text(
|
||||
englishOn ? "Simplified Chinese" : "English",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
];
|
||||
children
|
||||
.addAll(PolicyAndTermsText().getPrivacyPolicyText(context, englishOn));
|
||||
return MihSingleChildScroll(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: children,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/about_mih/mih_policy_tos_ext/policy_and_terms_text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MIHTermsOfService extends StatefulWidget {
|
||||
const MIHTermsOfService({super.key});
|
||||
|
||||
@override
|
||||
State<MIHTermsOfService> createState() => _MIHTermsOfServiceState();
|
||||
}
|
||||
|
||||
class _MIHTermsOfServiceState extends State<MIHTermsOfService> {
|
||||
bool englishOn = true;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(context),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(BuildContext context) {
|
||||
List<Widget> children = [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
englishOn = !englishOn;
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
child: Text(
|
||||
englishOn ? "Simplified Chinese" : "English",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
];
|
||||
children
|
||||
.addAll(PolicyAndTermsText().getTermsOfServiceText(context, englishOn));
|
||||
return MihSingleChildScroll(
|
||||
child: Column(
|
||||
children: children,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/access_request.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/app_user.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
|
||||
class BuildAccessRequestList extends StatefulWidget {
|
||||
final List<AccessRequest> accessRequests;
|
||||
final AppUser signedInUser;
|
||||
|
||||
const BuildAccessRequestList({
|
||||
super.key,
|
||||
required this.accessRequests,
|
||||
required this.signedInUser,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildAccessRequestList> createState() => _BuildPatientsListState();
|
||||
}
|
||||
|
||||
class _BuildPatientsListState extends State<BuildAccessRequestList> {
|
||||
String baseAPI = AppEnviroment.baseApiUrl;
|
||||
late double popUpWidth;
|
||||
late double? popUpheight;
|
||||
late double popUpButtonWidth;
|
||||
late double popUpTitleSize;
|
||||
late double popUpSubtitleSize;
|
||||
late double popUpBodySize;
|
||||
late double popUpIconSize;
|
||||
late double popUpPaddingSize;
|
||||
late double width;
|
||||
late double height;
|
||||
|
||||
Future<void> updateAccessAPICall(int index, String accessType) async {
|
||||
var response = await http.put(
|
||||
Uri.parse("$baseAPI/access-requests/update/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
"business_id": widget.accessRequests[index].business_id,
|
||||
"app_id": widget.accessRequests[index].app_id,
|
||||
"date_time": widget.accessRequests[index].date_time,
|
||||
"access": accessType,
|
||||
}),
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
//Navigator.of(context).pushNamed('/home');
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pushNamed(
|
||||
'/patient-access-review',
|
||||
arguments: widget.signedInUser,
|
||||
);
|
||||
String message = "";
|
||||
if (accessType == "approved") {
|
||||
message =
|
||||
"You've successfully approved the access request! ${widget.accessRequests[index].Name} now has access to your profile until ${widget.accessRequests[index].revoke_date.substring(0, 16).replaceAll("T", " ")}.";
|
||||
} else {
|
||||
message =
|
||||
"You've declined the access request. ${widget.accessRequests[index].Name} will not have access to your profile.";
|
||||
}
|
||||
MihAlertServices().successBasicAlert(
|
||||
"Success!",
|
||||
message,
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
Widget displayQueue(int index) {
|
||||
String line1 =
|
||||
"Appointment: ${widget.accessRequests[index].date_time.substring(0, 16).replaceAll("T", " ")}";
|
||||
String line2 = "";
|
||||
line2 += "Requestor: ${widget.accessRequests[index].Name}\n";
|
||||
//subtitle += "Business Type: ${widget.accessRequests[index].type}\n";
|
||||
String line3 = "Access: ";
|
||||
String access = "";
|
||||
var nowDate = DateTime.now();
|
||||
var expireyDate = DateTime.parse(widget.accessRequests[index].revoke_date);
|
||||
|
||||
if (expireyDate.isBefore(nowDate)) {
|
||||
access += "EXPIRED";
|
||||
} else {
|
||||
access += "${widget.accessRequests[index].access.toUpperCase()}";
|
||||
}
|
||||
String line4 = "";
|
||||
if (widget.accessRequests[index].revoke_date.contains("9999")) {
|
||||
line4 += "Access Expiration date: NOT SET";
|
||||
} else {
|
||||
line4 +=
|
||||
"Access Expiration date: ${widget.accessRequests[index].revoke_date.substring(0, 10)}";
|
||||
}
|
||||
TextSpan accessWithColour;
|
||||
if (access == "APPROVED") {
|
||||
accessWithColour = TextSpan(
|
||||
text: "$access\n",
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
|
||||
} else if (access == "PENDING") {
|
||||
accessWithColour = TextSpan(
|
||||
text: "$access\n",
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreyColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
|
||||
} else {
|
||||
accessWithColour = TextSpan(
|
||||
text: "$access\n",
|
||||
style: TextStyle(
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
|
||||
}
|
||||
|
||||
return ListTile(
|
||||
title: Text(
|
||||
line1,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
subtitle: RichText(
|
||||
text: TextSpan(
|
||||
text: line2,
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: line3),
|
||||
accessWithColour,
|
||||
TextSpan(text: line4),
|
||||
]),
|
||||
),
|
||||
// Text(
|
||||
// subtitle,
|
||||
// style: TextStyle(
|
||||
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
// ),
|
||||
onTap: () {
|
||||
if (access == "CANCELLED") {
|
||||
MihAlertServices().warningAlert(
|
||||
"Access Cancelled",
|
||||
"This appointment has been canceled. As a result, access has been cancelled and the doctor no longer have access to the patient's profile. If you would like them to view the patient's profile again, please book a new appointment through them.",
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
viewApprovalPopUp(index);
|
||||
}
|
||||
},
|
||||
// trailing: Icon(
|
||||
// Icons.arrow_forward,
|
||||
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
);
|
||||
}
|
||||
|
||||
void checkScreenSize() {
|
||||
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
|
||||
setState(() {
|
||||
popUpWidth = (width / 4) * 2;
|
||||
popUpheight = null;
|
||||
popUpButtonWidth = 300;
|
||||
popUpTitleSize = 25.0;
|
||||
popUpSubtitleSize = 20.0;
|
||||
popUpBodySize = 15;
|
||||
popUpPaddingSize = 25.0;
|
||||
popUpIconSize = 100;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
popUpWidth = width - (width * 0.1);
|
||||
popUpheight = null;
|
||||
popUpButtonWidth = 300;
|
||||
popUpTitleSize = 20.0;
|
||||
popUpSubtitleSize = 18.0;
|
||||
popUpBodySize = 15;
|
||||
popUpPaddingSize = 15.0;
|
||||
popUpIconSize = 100;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void viewApprovalPopUp(int index) {
|
||||
String subtitle =
|
||||
"Appointment: ${widget.accessRequests[index].date_time.substring(0, 16).replaceAll("T", " ")}\n";
|
||||
subtitle += "Requestor: ${widget.accessRequests[index].Name}\n";
|
||||
subtitle += "Business Type: ${widget.accessRequests[index].type}\n\n";
|
||||
subtitle +=
|
||||
"You are about to approve an access request to your patient profile.\nPlease be aware that once approved, ${widget.accessRequests[index].Name} will have access to your profile information until ${widget.accessRequests[index].revoke_date.substring(0, 16).replaceAll("T", " ")}.\nIf you are unsure about an upcoming appointment with ${widget.accessRequests[index].Name}, please contact ${widget.accessRequests[index].contact_no} for clarification before approving this request.\n";
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Update Appointment Access",
|
||||
windowBody: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Text(
|
||||
subtitle,
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: popUpBodySize,
|
||||
//fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
runSpacing: 10,
|
||||
spacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
updateAccessAPICall(index, "declined");
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Decline",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
updateAccessAPICall(index, "approved");
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Approve",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
onWindowTapClose: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
setState(() {
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
});
|
||||
checkScreenSize();
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
separatorBuilder: (BuildContext context, index) {
|
||||
return Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
},
|
||||
itemCount: widget.accessRequests.length,
|
||||
itemBuilder: (context, index) {
|
||||
//final patient = widget.patients[index].id_no.contains(widget.searchString);
|
||||
//print(index);
|
||||
return displayQueue(index);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,507 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/patient_access.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_access_controlls_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_access_controls_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class BuildBusinessAccessList extends StatefulWidget {
|
||||
final String filterText;
|
||||
final void Function()? onSuccessUpate;
|
||||
|
||||
const BuildBusinessAccessList({
|
||||
super.key,
|
||||
required this.filterText,
|
||||
required this.onSuccessUpate,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildBusinessAccessList> createState() => _BuildPatientsListState();
|
||||
}
|
||||
|
||||
class _BuildPatientsListState extends State<BuildBusinessAccessList> {
|
||||
String baseAPI = AppEnviroment.baseApiUrl;
|
||||
late double popUpWidth;
|
||||
late double? popUpheight;
|
||||
late double popUpButtonWidth;
|
||||
late double popUpTitleSize;
|
||||
late double popUpSubtitleSize;
|
||||
late double popUpBodySize;
|
||||
late double popUpIconSize;
|
||||
late double popUpPaddingSize;
|
||||
late double width;
|
||||
late double height;
|
||||
|
||||
Widget displayQueue(
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MihAccessControllsProvider accessProvider,
|
||||
int index,
|
||||
List<PatientAccess> filteredList) {
|
||||
String line1 = "Business Name: ${filteredList[index].requested_by}";
|
||||
String line2 = "";
|
||||
|
||||
line2 +=
|
||||
"Request Date: ${filteredList[index].requested_on.substring(0, 16).replaceAll("T", " ")}\n";
|
||||
line2 += "Profile Type: ${filteredList[index].type.toUpperCase()}\n";
|
||||
//subtitle += "Business Type: ${widget.patientAccessList[index].type}\n";
|
||||
String line3 = "Status: ";
|
||||
String access = filteredList[index].status.toUpperCase();
|
||||
|
||||
TextSpan accessWithColour;
|
||||
if (access == "APPROVED") {
|
||||
accessWithColour = TextSpan(
|
||||
text: "$access\n",
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
|
||||
} else if (access == "PENDING") {
|
||||
accessWithColour = TextSpan(
|
||||
text: "$access\n",
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreyColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
|
||||
} else {
|
||||
accessWithColour = TextSpan(
|
||||
text: "$access\n",
|
||||
style: TextStyle(
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
|
||||
}
|
||||
|
||||
return ListTile(
|
||||
title: Text(
|
||||
line1,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
subtitle: RichText(
|
||||
text: TextSpan(
|
||||
text: line2,
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: line3),
|
||||
accessWithColour,
|
||||
]),
|
||||
),
|
||||
// Text(
|
||||
// subtitle,
|
||||
// style: TextStyle(
|
||||
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
// ),
|
||||
onTap: () {
|
||||
viewApprovalPopUp(mzansiProfileProvider, accessProvider, index);
|
||||
},
|
||||
// trailing: Icon(
|
||||
// Icons.arrow_forward,
|
||||
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
);
|
||||
}
|
||||
|
||||
void checkScreenSize() {
|
||||
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
|
||||
setState(() {
|
||||
popUpWidth = (width / 4) * 2;
|
||||
popUpheight = null;
|
||||
popUpButtonWidth = 300;
|
||||
popUpTitleSize = 25.0;
|
||||
popUpSubtitleSize = 20.0;
|
||||
popUpBodySize = 15;
|
||||
popUpPaddingSize = 25.0;
|
||||
popUpIconSize = 100;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
popUpWidth = width - (width * 0.1);
|
||||
popUpheight = null;
|
||||
popUpButtonWidth = 300;
|
||||
popUpTitleSize = 20.0;
|
||||
popUpSubtitleSize = 18.0;
|
||||
popUpBodySize = 15;
|
||||
popUpPaddingSize = 15.0;
|
||||
popUpIconSize = 100;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void viewApprovalPopUp(MzansiProfileProvider mzansiProfileProvider,
|
||||
MihAccessControllsProvider accessProvider, int index) {
|
||||
String subtitle =
|
||||
"Business Name: ${accessProvider.accessList![index].requested_by}\n";
|
||||
subtitle +=
|
||||
"Requested Date: ${accessProvider.accessList![index].requested_on.substring(0, 16).replaceAll("T", " ")}\n";
|
||||
|
||||
subtitle +=
|
||||
"Profile Type: ${accessProvider.accessList![index].type.toUpperCase()}\n";
|
||||
subtitle +=
|
||||
"Status: ${accessProvider.accessList![index].status.toUpperCase()}";
|
||||
if (accessProvider.accessList![index].status == 'pending') {
|
||||
// "\nYou are about to approve an access request to your patient profile.\nPlease be aware that once approved, ${widget.patientAccessList[index].requested_by} will have access to your profile forever and will be able to contribute to it.\nIf you are unsure about an upcoming appointment with ${widget.patientAccessList[index].requested_by}, please contact *Add Number here* for clarification before approving this request.";
|
||||
} else {
|
||||
subtitle +=
|
||||
"\nActioned By: ${accessProvider.accessList![index].approved_by}\n";
|
||||
subtitle +=
|
||||
"Actioned On: ${accessProvider.accessList![index].approved_on.substring(0, 16).replaceAll("T", " ")}";
|
||||
// subtitle +=
|
||||
// "You have approved this access request to your patient profile.\nPlease be aware that once approved, ${widget.patientAccessList[index].requested_by} will have access to your profile forever and will be able to contribute to it.";
|
||||
}
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Profile Access",
|
||||
windowBody: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
SizedBox(
|
||||
width: 1000,
|
||||
child: Text(
|
||||
subtitle,
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: popUpBodySize,
|
||||
//fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20.0),
|
||||
Visibility(
|
||||
visible: accessProvider.accessList![index].status == 'pending',
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Important Notice: Approving Profile Access",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"You are about to accept access to your patient's profile. Please be aware of the following important points:",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: Text(
|
||||
"1. Permanent Access: Once you accepts this access request, it will become permanent.",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: Text(
|
||||
"2. Shared Information: Any updates make to youe patient profile will be visible to all who have access to the profile.",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: Text(
|
||||
"3. Irreversible Access: Once granted, you cannot revoke access to your patient's profile.",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"By pressing the \"Approve\" button you accept the above terms.",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: accessProvider.accessList![index].status == 'approved',
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Important Notice: Approved Profile Access",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"You have accepted access to your patient's profile. Please be aware of the following important points:",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: Text(
|
||||
"1. Permanent Access: This access is permanent.",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: Text(
|
||||
"2. Shared Information: Any updates make to youe patient profile will be visible to all who have access to the profile.",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: Text(
|
||||
"3. Irreversible Access: You cannot revoke this access to your patient's profile.",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20.0),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Visibility(
|
||||
visible: accessProvider.accessList![index].status == 'pending',
|
||||
child: Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
runSpacing: 10,
|
||||
spacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () async {
|
||||
print("request declined");
|
||||
int statusCode = await MihAccessControlsServices()
|
||||
.updatePatientAccessAPICall(
|
||||
accessProvider.accessList![index].business_id,
|
||||
accessProvider.accessList![index].requested_by,
|
||||
accessProvider.accessList![index].app_id,
|
||||
"declined",
|
||||
"${mzansiProfileProvider.user!.fname} ${mzansiProfileProvider.user!.lname}",
|
||||
mzansiProfileProvider.user!,
|
||||
context,
|
||||
);
|
||||
if (statusCode == 200) {
|
||||
await MihAccessControlsServices()
|
||||
.getBusinessAccessListOfPatient(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
accessProvider,
|
||||
);
|
||||
context.pop();
|
||||
successPopUp("Successfully Actioned Request",
|
||||
"You have successfully Declined access request");
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Decline",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () async {
|
||||
print("request approved");
|
||||
int statusCode = await MihAccessControlsServices()
|
||||
.updatePatientAccessAPICall(
|
||||
accessProvider.accessList![index].business_id,
|
||||
accessProvider.accessList![index].requested_by,
|
||||
accessProvider.accessList![index].app_id,
|
||||
"approved",
|
||||
"${mzansiProfileProvider.user!.fname} ${mzansiProfileProvider.user!.lname}",
|
||||
mzansiProfileProvider.user!,
|
||||
context,
|
||||
);
|
||||
if (statusCode == 200) {
|
||||
await MihAccessControlsServices()
|
||||
.getBusinessAccessListOfPatient(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
accessProvider,
|
||||
);
|
||||
context.pop();
|
||||
successPopUp("Successfully Actioned Request",
|
||||
"You have successfully Accepted access request");
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Approve",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
onWindowTapClose: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
void successPopUp(String title, String message) {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
title,
|
||||
message,
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
KenLogger.warning("dismissing pop up and refreshing list");
|
||||
if (widget.onSuccessUpate != null) {
|
||||
widget.onSuccessUpate!();
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
List<PatientAccess> filterAccessList(List<PatientAccess> accessList) {
|
||||
if (widget.filterText == "All") {
|
||||
return accessList;
|
||||
}
|
||||
return accessList
|
||||
.where((item) =>
|
||||
item.status.toLowerCase() == widget.filterText.toLowerCase())
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
setState(() {
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
});
|
||||
checkScreenSize();
|
||||
return Consumer2<MzansiProfileProvider, MihAccessControllsProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MihAccessControllsProvider accessProvider,
|
||||
Widget? child) {
|
||||
return ListView.separated(
|
||||
separatorBuilder: (BuildContext context, index) {
|
||||
return Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
},
|
||||
itemCount: filterAccessList(accessProvider.accessList!).length,
|
||||
itemBuilder: (context, index) {
|
||||
//final patient = widget.patients[index].id_no.contains(widget.searchString);
|
||||
//print(index);
|
||||
final filteredList = filterAccessList(accessProvider.accessList!);
|
||||
return displayQueue(
|
||||
mzansiProfileProvider, accessProvider, index, filteredList);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
111
mih_ui/lib/mih_packages/access_review/mih_access.dart
Normal file
111
mih_ui/lib/mih_packages/access_review/mih_access.dart
Normal file
@@ -0,0 +1,111 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_access_controlls_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/access_review/package_tools/mih_access_requests.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_data_helper_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihAccess extends StatefulWidget {
|
||||
const MihAccess({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihAccess> createState() => _MihAccessState();
|
||||
}
|
||||
|
||||
class _MihAccessState extends State<MihAccess> {
|
||||
bool _isLoadingInitialData = true;
|
||||
late final MihAccessRequest _accessRequest;
|
||||
|
||||
Future<void> _loadInitialData() async {
|
||||
setState(() {
|
||||
_isLoadingInitialData = true;
|
||||
});
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
if (mzansiProfileProvider.user == null) {
|
||||
await MihDataHelperServices().loadUserDataOnly(
|
||||
mzansiProfileProvider,
|
||||
);
|
||||
}
|
||||
setState(() {
|
||||
_isLoadingInitialData = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_accessRequest = MihAccessRequest();
|
||||
_loadInitialData();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MihAccessControllsProvider>(
|
||||
builder: (BuildContext context, MihAccessControllsProvider accessProvider,
|
||||
Widget? child) {
|
||||
if (_isLoadingInitialData) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Mihloadingcircle(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: accessProvider.toolIndex,
|
||||
onIndexChange: (newValue) {
|
||||
accessProvider.setToolIndex(newValue);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.people)] = () {
|
||||
context.read<MihAccessControllsProvider>().setToolIndex(0);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MihAccessControllsProvider>().toolIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_accessRequest,
|
||||
];
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Access",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:go_router/go_router.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_package_components/mih_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MihAccessTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
|
||||
const MihAccessTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihAccessTile> createState() => _MihAccessTileState();
|
||||
}
|
||||
|
||||
class _MihAccessTileState extends State<MihAccessTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageTile(
|
||||
authenticateUser: true,
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
"mihAccess",
|
||||
);
|
||||
// Navigator.of(context).pushNamed(
|
||||
// '/mih-access',
|
||||
// arguments: widget.signedInUser,
|
||||
// );
|
||||
},
|
||||
appName: "Access Controls",
|
||||
appIcon: Icon(
|
||||
MihIcons.accessControl,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: widget.packageSize,
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/patient_access.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_access_controlls_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/access_review/builder/build_business_access_list.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_access_controls_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihAccessRequest extends StatefulWidget {
|
||||
const MihAccessRequest({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihAccessRequest> createState() => _MihAccessRequestState();
|
||||
}
|
||||
|
||||
class _MihAccessRequestState extends State<MihAccessRequest> {
|
||||
TextEditingController filterController = TextEditingController();
|
||||
bool isLoading = true;
|
||||
String baseUrl = AppEnviroment.baseApiUrl;
|
||||
|
||||
String errorCode = "";
|
||||
String errorBody = "";
|
||||
String datefilter = "";
|
||||
String accessFilter = "";
|
||||
bool forceRefresh = false;
|
||||
late String selectedDropdown;
|
||||
|
||||
List<PatientAccess> filterSearchResults(List<PatientAccess> accessList) {
|
||||
List<PatientAccess> templist = [];
|
||||
for (var item in accessList) {
|
||||
if (filterController.text == "All") {
|
||||
templist.add(item);
|
||||
} else {
|
||||
if (item.status.contains(filterController.text.toLowerCase())) {
|
||||
templist.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return templist;
|
||||
}
|
||||
|
||||
void refreshList() {
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
MihAccessControllsProvider accessProvider =
|
||||
context.read<MihAccessControllsProvider>();
|
||||
if (forceRefresh == true) {
|
||||
MihAccessControlsServices().getBusinessAccessListOfPatient(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
accessProvider,
|
||||
);
|
||||
setState(() {
|
||||
forceRefresh = false;
|
||||
});
|
||||
} else if (selectedDropdown != filterController.text) {
|
||||
MihAccessControlsServices().getBusinessAccessListOfPatient(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
accessProvider,
|
||||
);
|
||||
setState(() {
|
||||
selectedDropdown = filterController.text;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Widget getBody() {
|
||||
return Consumer2<MzansiProfileProvider, MihAccessControllsProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MihAccessControllsProvider accessProvider,
|
||||
Widget? child) {
|
||||
if (isLoading) {
|
||||
return const Center(
|
||||
child: Mihloadingcircle(),
|
||||
);
|
||||
}
|
||||
return Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
child: MihDropdownField(
|
||||
controller: filterController,
|
||||
hintText: "Access Type",
|
||||
dropdownOptions: const [
|
||||
"All",
|
||||
"Approved",
|
||||
"Pending",
|
||||
"Declined",
|
||||
"Cancelled",
|
||||
],
|
||||
requiredText: true,
|
||||
editable: true,
|
||||
enableSearch: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
iconSize: 35,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
forceRefresh = true;
|
||||
});
|
||||
KenLogger.warning("Refreshing Access List");
|
||||
refreshList();
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.refresh,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: BuildBusinessAccessList(
|
||||
filterText: filterController.text,
|
||||
onSuccessUpate: () {
|
||||
setState(() {
|
||||
forceRefresh = true;
|
||||
});
|
||||
refreshList();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> initiasizeAccessList() async {
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
MihAccessControllsProvider accessProvider =
|
||||
context.read<MihAccessControllsProvider>();
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
await MihAccessControlsServices().getBusinessAccessListOfPatient(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
accessProvider,
|
||||
);
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
filterController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
selectedDropdown = "All";
|
||||
filterController.text = "All";
|
||||
filterController.addListener(refreshList);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await initiasizeAccessList();
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(),
|
||||
);
|
||||
}
|
||||
}
|
||||
102
mih_ui/lib/mih_packages/calculator/mih_calculator.dart
Normal file
102
mih_ui/lib/mih_packages/calculator/mih_calculator.dart
Normal file
@@ -0,0 +1,102 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_calculator_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tools/currency_exchange_rate.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tools/simple_calc.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tools/tip_calc.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_currency_exchange_rate_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MIHCalculator extends StatefulWidget {
|
||||
const MIHCalculator({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MIHCalculator> createState() => _MIHCalculatorState();
|
||||
}
|
||||
|
||||
class _MIHCalculatorState extends State<MIHCalculator> {
|
||||
late final SimpleCalc _simpleCalc;
|
||||
late final TipCalc _tipCalc;
|
||||
late final CurrencyExchangeRate _currencyExchangeRate;
|
||||
|
||||
Future<void> getCurrencyCodeList() async {
|
||||
await MihCurrencyExchangeRateServices.getCurrencyCodeList(context);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_simpleCalc = SimpleCalc();
|
||||
_tipCalc = TipCalc();
|
||||
_currencyExchangeRate = CurrencyExchangeRate();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await getCurrencyCodeList();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: context.watch<MihCalculatorProvider>().toolIndex,
|
||||
onIndexChange: (newIndex) {
|
||||
context.read<MihCalculatorProvider>().setToolIndex(newIndex);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.calculate)] = () {
|
||||
context.read<MihCalculatorProvider>().setToolIndex(0);
|
||||
};
|
||||
temp[const Icon(Icons.money)] = () {
|
||||
context.read<MihCalculatorProvider>().setToolIndex(1);
|
||||
};
|
||||
temp[const Icon(Icons.currency_exchange)] = () {
|
||||
context.read<MihCalculatorProvider>().setToolIndex(2);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MihCalculatorProvider>().toolIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_simpleCalc,
|
||||
_tipCalc,
|
||||
_currencyExchangeRate,
|
||||
];
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Simple Calculator",
|
||||
"Tip Calculator",
|
||||
"Forex Calculator",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tile.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MihCalculatorTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
|
||||
const MihCalculatorTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihCalculatorTile> createState() => _MihCalculatorTileState();
|
||||
}
|
||||
|
||||
class _MihCalculatorTileState extends State<MihCalculatorTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageTile(
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
"mihCalculator",
|
||||
);
|
||||
},
|
||||
appName: "Calculator",
|
||||
appIcon: Icon(
|
||||
MihIcons.calculator,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: widget.packageSize,
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,443 @@
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.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_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_calculator_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_currency_exchange_rate_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class CurrencyExchangeRate extends StatefulWidget {
|
||||
const CurrencyExchangeRate({super.key});
|
||||
|
||||
@override
|
||||
State<CurrencyExchangeRate> createState() => _CurrencyExchangeRateState();
|
||||
}
|
||||
|
||||
class _CurrencyExchangeRateState extends State<CurrencyExchangeRate> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final TextEditingController _fromCurrencyController = TextEditingController();
|
||||
final TextEditingController _toCurrencyController = TextEditingController();
|
||||
final TextEditingController _fromAmountController = TextEditingController();
|
||||
final TextEditingController _toAmountController = TextEditingController();
|
||||
|
||||
Future<void> submitForm() async {
|
||||
String fromCurrencyCode = _fromCurrencyController.text.split(" - ")[0];
|
||||
String toCurrencyCode = _toCurrencyController.text.split(" - ")[0];
|
||||
List<String> dateValue = [];
|
||||
double exchangeRate = 0;
|
||||
await MihCurrencyExchangeRateServices.getCurrencyExchangeValue(
|
||||
fromCurrencyCode, toCurrencyCode)
|
||||
.then((amount) {
|
||||
dateValue = amount;
|
||||
});
|
||||
exchangeRate = double.parse(dateValue[1]);
|
||||
double exchangeValue =
|
||||
double.parse(_fromAmountController.text) * exchangeRate;
|
||||
|
||||
print(
|
||||
"Date: ${dateValue[0]}\n${_fromAmountController.text} | $fromCurrencyCode\n$exchangeValue | $toCurrencyCode");
|
||||
displayResult(dateValue[0], _fromAmountController.text, fromCurrencyCode,
|
||||
exchangeValue, toCurrencyCode);
|
||||
}
|
||||
|
||||
void clearInput() {
|
||||
_fromCurrencyController.clear();
|
||||
_fromAmountController.clear();
|
||||
_toCurrencyController.clear();
|
||||
_toAmountController.clear();
|
||||
}
|
||||
|
||||
void displayResult(String date, String amount, String fromCurrencyCode,
|
||||
double exchangeValue, String toCurrencyCode) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Calculation Results",
|
||||
onWindowTapClose: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
windowBody: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.currency_exchange,
|
||||
size: 150,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
"Values as at $date",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
amount,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Text(
|
||||
fromCurrencyCode.toUpperCase(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
exchangeValue.toStringAsFixed(2),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Text(
|
||||
toCurrencyCode.toUpperCase(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Consumer(builder: (context, bannerAdDisplay, child) {
|
||||
return MihBannerAd();
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void displayDisclaimer() {
|
||||
final String companyName = 'Mzansi Innovation Hub';
|
||||
|
||||
showDialog(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (context) => MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Disclaimer Notice",
|
||||
onWindowTapClose: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
windowBody: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Main Title
|
||||
|
||||
Text(
|
||||
'Disclaimer of Warranty and Limitation of Liability for Forex Calculator',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 24.0),
|
||||
|
||||
// First Paragraph - using RichText to bold "the Tool"
|
||||
_buildRichText(
|
||||
'The Forex Calculator feature ("',
|
||||
'the Tool',
|
||||
'") is provided on an "as is" and "as available" basis. It is an experimental feature and is intended solely for informational and illustrative purposes.',
|
||||
),
|
||||
const SizedBox(height: 16.0),
|
||||
|
||||
// Second Paragraph
|
||||
Text(
|
||||
'$companyName makes no representations or warranties of any kind, express or implied, as to the accuracy, completeness, reliability, or suitability of the information and calculations generated by the Tool. All exchange rates and results are estimates and are subject to change without notice.',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16.0),
|
||||
|
||||
// Third Paragraph
|
||||
Text(
|
||||
'The information provided by the Tool should not be construed as financial, investment, trading, or any other form of advice. You should not make any financial decisions based solely on the output of this Tool. We expressly recommend that you seek independent professional advice and verify all data with a qualified financial advisor and/or through alternative, reliable market data sources before executing any foreign exchange transactions.',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16.0),
|
||||
|
||||
// Fourth Paragraph
|
||||
Text(
|
||||
'By using the Tool, you agree that $companyName, its affiliates, directors, and employees shall not be held liable for any direct, indirect, incidental, special, consequential, or exemplary damages, including but not limited to, damages for loss of profits, goodwill, use, data, or other intangible losses, resulting from: (i) the use or the inability to use the Tool; (ii) any inaccuracies, errors, or omissions in the Tool\'s calculations or data; or (iii) any reliance placed by you on the information provided by the Tool.',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRichText(String start, String bold, String end) {
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: start),
|
||||
TextSpan(
|
||||
text: bold, style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||
TextSpan(text: end),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_fromCurrencyController.dispose();
|
||||
_fromAmountController.dispose();
|
||||
_toCurrencyController.dispose();
|
||||
_toAmountController.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(screenWidth),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return Consumer<MihCalculatorProvider>(
|
||||
builder: (context, calculatorProvider, child) {
|
||||
return MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.2)
|
||||
: EdgeInsets.symmetric(horizontal: width * 0.075),
|
||||
child: Column(
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: <Widget>[
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: _fromAmountController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Currency Amount",
|
||||
numberMode: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihDropdownField(
|
||||
controller: _fromCurrencyController,
|
||||
hintText: "From",
|
||||
dropdownOptions: calculatorProvider.availableCurrencies,
|
||||
editable: true,
|
||||
enableSearch: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
requiredText: true,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihDropdownField(
|
||||
controller: _toCurrencyController,
|
||||
hintText: "To",
|
||||
dropdownOptions: calculatorProvider.availableCurrencies,
|
||||
editable: true,
|
||||
enableSearch: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
requiredText: true,
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
RichText(
|
||||
textAlign: TextAlign.left,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
const TextSpan(
|
||||
text: "* Experimental Feature: Please review "),
|
||||
TextSpan(
|
||||
text: "Diclaimer",
|
||||
style: TextStyle(
|
||||
decoration: TextDecoration.underline,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
displayDisclaimer();
|
||||
},
|
||||
),
|
||||
const TextSpan(text: " before use."),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitForm();
|
||||
FocusScope.of(context)
|
||||
.requestFocus(FocusNode());
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Calculate",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
clearInput();
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Clear",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:math_expressions/math_expressions.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class SimpleCalc extends StatefulWidget {
|
||||
const SimpleCalc({super.key});
|
||||
|
||||
@override
|
||||
State<SimpleCalc> createState() => _SimpleCalcState();
|
||||
}
|
||||
|
||||
class _SimpleCalcState extends State<SimpleCalc> {
|
||||
var userInput = '';
|
||||
var answer = '0';
|
||||
|
||||
// Array of button
|
||||
final List<String> buttons = [
|
||||
'AC',
|
||||
'(',
|
||||
')',
|
||||
'÷',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'x',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'-',
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'+',
|
||||
'0',
|
||||
'.',
|
||||
'D',
|
||||
'=',
|
||||
];
|
||||
|
||||
// function to calculate the input operation
|
||||
void equalPressed() {
|
||||
String finaluserinput = userInput;
|
||||
finaluserinput = finaluserinput.replaceAll('x', '*');
|
||||
finaluserinput = finaluserinput.replaceAll('÷', '/');
|
||||
print(finaluserinput);
|
||||
|
||||
Parser p = Parser();
|
||||
Expression exp = p.parse(finaluserinput);
|
||||
ContextModel cm = ContextModel();
|
||||
double eval = exp.evaluate(EvaluationType.REAL, cm);
|
||||
if (eval.toString().length <= 1) {
|
||||
} else if (eval
|
||||
.toString()
|
||||
.substring(eval.toString().length - 2, eval.toString().length) ==
|
||||
".0") {
|
||||
answer = eval.toString().substring(0, eval.toString().length - 2);
|
||||
} else {
|
||||
answer = eval.toString();
|
||||
}
|
||||
}
|
||||
|
||||
bool isNumeric(String? s) {
|
||||
if (s == null) {
|
||||
return false;
|
||||
}
|
||||
return double.tryParse(s) != null;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody() {
|
||||
// double width = MediaQuery.sizeOf(context).width;
|
||||
double height = MediaQuery.sizeOf(context).height;
|
||||
// var padding = MediaQuery.paddingOf(context);
|
||||
// double newheight = height - padding.top - padding.bottom;
|
||||
// print("width: $width");
|
||||
// print("height: $height");
|
||||
// print("newheight: $newheight");
|
||||
double calcWidth = 500;
|
||||
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
|
||||
if (height < 700) {
|
||||
calcWidth = 300;
|
||||
}
|
||||
}
|
||||
return MihSingleChildScroll(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
alignment: Alignment.centerRight,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
reverse: true,
|
||||
child: Text(
|
||||
userInput,
|
||||
style: TextStyle(
|
||||
fontSize: 40,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
//color: Colors.white,
|
||||
padding: const EdgeInsets.all(15),
|
||||
alignment: Alignment.centerRight,
|
||||
child: Text(
|
||||
answer,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.centerRight,
|
||||
child: SizedBox(
|
||||
width: calcWidth,
|
||||
child: GridView.builder(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
// padding: EdgeInsets.only(
|
||||
// left: width / 10,
|
||||
// right: width / 10,
|
||||
// bottom: height / 15,
|
||||
// //top: 20,
|
||||
// ),
|
||||
// shrinkWrap: true,
|
||||
itemCount: buttons.length,
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 4,
|
||||
//mainAxisExtent: 150,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
// Clear Button
|
||||
if (index == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
userInput = '';
|
||||
answer = '0';
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getPurpleColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 50,
|
||||
height: 50,
|
||||
borderRadius: 5,
|
||||
child: Text(
|
||||
buttons[index],
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// ( button
|
||||
else if (index == 1) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
userInput += buttons[index];
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getGreyColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 50,
|
||||
height: 50,
|
||||
borderRadius: 5,
|
||||
child: Text(
|
||||
buttons[index],
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
// ) Button
|
||||
else if (index == 2) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
userInput += buttons[index];
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getGreyColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 50,
|
||||
height: 50,
|
||||
borderRadius: 5,
|
||||
child: Text(
|
||||
buttons[index],
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
// +, -, / x buttons
|
||||
else if (index == 3 ||
|
||||
index == 7 ||
|
||||
index == 11 ||
|
||||
index == 15) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
if (answer == "0") {
|
||||
setState(() {
|
||||
userInput += buttons[index];
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
// userInput = answer;
|
||||
// answer = "0";
|
||||
userInput += buttons[index];
|
||||
});
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreyColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 50,
|
||||
height: 50,
|
||||
borderRadius: 5,
|
||||
child: Text(
|
||||
buttons[index],
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// delete Button
|
||||
else if (index == 18) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
if (userInput.length == 1) {
|
||||
userInput = '0';
|
||||
} else if (userInput.length > 1) {
|
||||
userInput =
|
||||
userInput.substring(0, userInput.length - 1);
|
||||
}
|
||||
if (!isNumeric(userInput[userInput.length - 1])) {
|
||||
userInput =
|
||||
userInput.substring(0, userInput.length - 1);
|
||||
}
|
||||
equalPressed();
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 50,
|
||||
height: 50,
|
||||
borderRadius: 5,
|
||||
child: Icon(
|
||||
Icons.backspace,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
// Equal_to Button
|
||||
else if (index == 19) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
equalPressed();
|
||||
userInput = answer;
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 50,
|
||||
height: 50,
|
||||
borderRadius: 5,
|
||||
child: Text(
|
||||
buttons[index],
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
// other buttons
|
||||
else {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(4.0),
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
userInput += buttons[index];
|
||||
equalPressed();
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 50,
|
||||
height: 50,
|
||||
borderRadius: 5,
|
||||
child: Text(
|
||||
buttons[index],
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
445
mih_ui/lib/mih_packages/calculator/package_tools/tip_calc.dart
Normal file
445
mih_ui/lib/mih_packages/calculator/package_tools/tip_calc.dart
Normal file
@@ -0,0 +1,445 @@
|
||||
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_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_numeric_stepper.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:math_expressions/math_expressions.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_toggle.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class TipCalc extends StatefulWidget {
|
||||
const TipCalc({super.key});
|
||||
|
||||
@override
|
||||
State<TipCalc> createState() => _TipCalcState();
|
||||
}
|
||||
|
||||
class _TipCalcState extends State<TipCalc> {
|
||||
TextEditingController billAmountController = TextEditingController();
|
||||
TextEditingController tipPercentageController = TextEditingController();
|
||||
TextEditingController splitBillController = TextEditingController();
|
||||
TextEditingController noPeopleController = TextEditingController();
|
||||
final ValueNotifier<String> splitValue = ValueNotifier("");
|
||||
late bool splitPosition;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
String tip = "";
|
||||
String total = "";
|
||||
String amountPerPerson = "";
|
||||
String temp = "";
|
||||
void splitSelected() {
|
||||
if (splitBillController.text.isNotEmpty) {
|
||||
splitValue.value = splitBillController.text;
|
||||
} else {
|
||||
splitValue.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
void validateInput() async {
|
||||
calculatePressed();
|
||||
}
|
||||
|
||||
void calculatePressed() {
|
||||
String tipCalc =
|
||||
"${billAmountController.text}*(${tipPercentageController.text}/100)";
|
||||
Parser p = Parser();
|
||||
ContextModel cm = ContextModel();
|
||||
Expression exp = p.parse(tipCalc);
|
||||
double eval = exp.evaluate(EvaluationType.REAL, cm);
|
||||
tip = eval.toStringAsFixed(2);
|
||||
//print("Tip: $tip");
|
||||
String totalCalc = "${billAmountController.text}+$tip";
|
||||
exp = p.parse(totalCalc);
|
||||
eval = exp.evaluate(EvaluationType.REAL, cm);
|
||||
total = eval.toStringAsFixed(2);
|
||||
//print("Total Amount: $total");
|
||||
if (splitBillController.text == "Yes") {
|
||||
String splitCalc = "$total/${noPeopleController.text}";
|
||||
exp = p.parse(splitCalc);
|
||||
eval = exp.evaluate(EvaluationType.REAL, cm);
|
||||
amountPerPerson = eval.toStringAsFixed(2);
|
||||
}
|
||||
|
||||
//print("Amount Per Person: $amountPerPerson");
|
||||
displayResult();
|
||||
}
|
||||
|
||||
void clearInput() {
|
||||
billAmountController.clear();
|
||||
tipPercentageController.clear();
|
||||
noPeopleController.clear();
|
||||
setState(() {
|
||||
splitBillController.text = "No";
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
billAmountController.dispose();
|
||||
tipPercentageController.dispose();
|
||||
splitBillController.dispose();
|
||||
noPeopleController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void displayResult() {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Calculation Results",
|
||||
onWindowTapClose: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
windowBody: Column(
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
FaIcon(
|
||||
FontAwesomeIcons.coins,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
size: 35,
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Text(
|
||||
"Tip",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
tip,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
FaIcon(
|
||||
FontAwesomeIcons.moneyBills,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
size: 35,
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Text(
|
||||
"Total",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
total,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"~ ${double.parse(total).ceil()}.00",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
if (splitBillController.text == "Yes") const Divider(),
|
||||
if (splitBillController.text == "Yes")
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
FaIcon(
|
||||
FontAwesomeIcons.peopleGroup,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
size: 35,
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Text(
|
||||
"Total per Person",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (splitBillController.text == "Yes")
|
||||
Text(
|
||||
amountPerPerson,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
if (splitBillController.text == "Yes")
|
||||
Text(
|
||||
"~ ${double.parse(amountPerPerson).ceil()}.00",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
Consumer(builder: (context, bannerAdDisplay, child) {
|
||||
return MihBannerAd();
|
||||
}),
|
||||
// if (splitBillController.text == "Yes") const Divider(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
splitBillController.text = "No";
|
||||
noPeopleController.text = "2";
|
||||
splitPosition = false;
|
||||
splitBillController.addListener(splitSelected);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(screenWidth),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.2)
|
||||
: EdgeInsets.symmetric(horizontal: width * 0.075),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: <Widget>[
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: billAmountController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Bill Amount",
|
||||
numberMode: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: tipPercentageController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Tip Percentage",
|
||||
numberMode: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihToggle(
|
||||
hintText: "Split Bill",
|
||||
initialPostion: splitPosition,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
secondaryFillColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onChange: (value) {
|
||||
setState(() {
|
||||
splitBillController.text = value ? "Yes" : "No";
|
||||
splitPosition = value;
|
||||
if (value) {
|
||||
noPeopleController.text =
|
||||
noPeopleController.text.isEmpty
|
||||
? "2"
|
||||
: noPeopleController.text;
|
||||
} else {
|
||||
noPeopleController.clear();
|
||||
}
|
||||
});
|
||||
// if (value) {
|
||||
// setState(() {
|
||||
// splitBillController.text = "Yes";
|
||||
// splitPosition = value;
|
||||
// });
|
||||
// } else {
|
||||
// setState(() {
|
||||
// splitBillController.text = "No";
|
||||
// splitPosition = value;
|
||||
// });
|
||||
// }
|
||||
},
|
||||
),
|
||||
ValueListenableBuilder(
|
||||
valueListenable: splitValue,
|
||||
builder: (BuildContext context, String value, Widget? child) {
|
||||
temp = value;
|
||||
return Visibility(
|
||||
visible: temp == "Yes",
|
||||
child: Column(
|
||||
children: [
|
||||
MihNumericStepper(
|
||||
controller: noPeopleController,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
hintText: "No. People",
|
||||
requiredText: temp == "Yes",
|
||||
minValue: 2,
|
||||
// maxValue: 5,
|
||||
validationOn: true,
|
||||
),
|
||||
// MihTextFormField(
|
||||
// fillColor: MzansiInnovationHub.of(context)!
|
||||
// .theme
|
||||
// .secondaryColor(),
|
||||
// inputColor: MzansiInnovationHub.of(context)!
|
||||
// .theme
|
||||
// .primaryColor(),
|
||||
// controller: noPeopleController,
|
||||
// multiLineInput: false,
|
||||
// requiredText: temp == "Yes",
|
||||
// hintText: "No. of People",
|
||||
// numberMode: true,
|
||||
// validator: (validationValue) {
|
||||
// if (temp == "Yes") {
|
||||
// return MihValidationServices()
|
||||
// .isEmpty(validationValue);
|
||||
// } else {
|
||||
// return null;
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Center(
|
||||
child: Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
validateInput();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Calculate",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
clearInput();
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Clear",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/access_request.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/app_user.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
|
||||
class BuildAccessRequestList extends StatefulWidget {
|
||||
final List<AccessRequest> accessRequests;
|
||||
final AppUser signedInUser;
|
||||
|
||||
const BuildAccessRequestList({
|
||||
super.key,
|
||||
required this.accessRequests,
|
||||
required this.signedInUser,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildAccessRequestList> createState() => _BuildPatientsListState();
|
||||
}
|
||||
|
||||
class _BuildPatientsListState extends State<BuildAccessRequestList> {
|
||||
String baseAPI = AppEnviroment.baseApiUrl;
|
||||
late double popUpWidth;
|
||||
late double? popUpheight;
|
||||
late double popUpButtonWidth;
|
||||
late double popUpTitleSize;
|
||||
late double popUpSubtitleSize;
|
||||
late double popUpBodySize;
|
||||
late double popUpIconSize;
|
||||
late double popUpPaddingSize;
|
||||
late double width;
|
||||
late double height;
|
||||
|
||||
Future<void> updateAccessAPICall(int index, String accessType) async {
|
||||
var response = await http.put(
|
||||
Uri.parse("$baseAPI/access-requests/update/"),
|
||||
headers: <String, String>{
|
||||
"Content-Type": "application/json; charset=UTF-8"
|
||||
},
|
||||
body: jsonEncode(<String, dynamic>{
|
||||
"business_id": widget.accessRequests[index].business_id,
|
||||
"app_id": widget.accessRequests[index].app_id,
|
||||
"date_time": widget.accessRequests[index].date_time,
|
||||
"access": accessType,
|
||||
}),
|
||||
);
|
||||
if (response.statusCode == 200) {
|
||||
//Navigator.of(context).pushNamed('/home');
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pushNamed(
|
||||
'/patient-access-review',
|
||||
arguments: widget.signedInUser,
|
||||
);
|
||||
String message = "";
|
||||
if (accessType == "approved") {
|
||||
message =
|
||||
"You've successfully approved the access request! ${widget.accessRequests[index].Name} now has access to your profile until ${widget.accessRequests[index].revoke_date.substring(0, 16).replaceAll("T", " ")}.";
|
||||
} else {
|
||||
message =
|
||||
"You've declined the access request. ${widget.accessRequests[index].Name} will not have access to your profile.";
|
||||
}
|
||||
MihAlertServices().successBasicAlert(
|
||||
"Success!",
|
||||
message,
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
Widget displayQueue(int index) {
|
||||
String line1 =
|
||||
"Appointment: ${widget.accessRequests[index].date_time.substring(0, 16).replaceAll("T", " ")}";
|
||||
String line2 = "";
|
||||
line2 += "Requestor: ${widget.accessRequests[index].Name}\n";
|
||||
//subtitle += "Business Type: ${widget.accessRequests[index].type}\n";
|
||||
String line3 = "Access: ";
|
||||
String access = "";
|
||||
var nowDate = DateTime.now();
|
||||
var expireyDate = DateTime.parse(widget.accessRequests[index].revoke_date);
|
||||
|
||||
if (expireyDate.isBefore(nowDate)) {
|
||||
access += "EXPIRED";
|
||||
} else {
|
||||
access += "${widget.accessRequests[index].access.toUpperCase()}";
|
||||
}
|
||||
String line4 = "";
|
||||
if (widget.accessRequests[index].revoke_date.contains("9999")) {
|
||||
line4 += "Access Expiration date: NOT SET";
|
||||
} else {
|
||||
line4 +=
|
||||
"Access Expiration date: ${widget.accessRequests[index].revoke_date.substring(0, 10)}";
|
||||
}
|
||||
TextSpan accessWithColour;
|
||||
if (access == "APPROVED") {
|
||||
accessWithColour = TextSpan(
|
||||
text: "$access\n",
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
|
||||
} else if (access == "PENDING") {
|
||||
accessWithColour = TextSpan(
|
||||
text: "$access\n",
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreyColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
|
||||
} else {
|
||||
accessWithColour = TextSpan(
|
||||
text: "$access\n",
|
||||
style: TextStyle(
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")));
|
||||
}
|
||||
|
||||
return ListTile(
|
||||
title: Text(
|
||||
line1,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
subtitle: RichText(
|
||||
text: TextSpan(
|
||||
text: line2,
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
children: <TextSpan>[
|
||||
TextSpan(text: line3),
|
||||
accessWithColour,
|
||||
TextSpan(text: line4),
|
||||
]),
|
||||
),
|
||||
// Text(
|
||||
// subtitle,
|
||||
// style: TextStyle(
|
||||
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
// ),
|
||||
onTap: () {
|
||||
if (access == "CANCELLED") {
|
||||
MihAlertServices().warningAlert(
|
||||
"Access Cancelled",
|
||||
"This appointment has been canceled. As a result, access has been cancelled and the doctor no longer have access to the patient's profile. If you would like them to view the patient's profile again, please book a new appointment through them.",
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
viewApprovalPopUp(index);
|
||||
}
|
||||
},
|
||||
// trailing: Icon(
|
||||
// Icons.arrow_forward,
|
||||
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
);
|
||||
}
|
||||
|
||||
void checkScreenSize() {
|
||||
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
|
||||
setState(() {
|
||||
popUpWidth = (width / 4) * 2;
|
||||
popUpheight = null;
|
||||
popUpButtonWidth = 300;
|
||||
popUpTitleSize = 25.0;
|
||||
popUpSubtitleSize = 20.0;
|
||||
popUpBodySize = 15;
|
||||
popUpPaddingSize = 25.0;
|
||||
popUpIconSize = 100;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
popUpWidth = width - (width * 0.1);
|
||||
popUpheight = null;
|
||||
popUpButtonWidth = 300;
|
||||
popUpTitleSize = 20.0;
|
||||
popUpSubtitleSize = 18.0;
|
||||
popUpBodySize = 15;
|
||||
popUpPaddingSize = 15.0;
|
||||
popUpIconSize = 100;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void viewApprovalPopUp(int index) {
|
||||
String subtitle =
|
||||
"Appointment: ${widget.accessRequests[index].date_time.substring(0, 16).replaceAll("T", " ")}\n";
|
||||
subtitle += "Requestor: ${widget.accessRequests[index].Name}\n";
|
||||
subtitle += "Business Type: ${widget.accessRequests[index].type}\n\n";
|
||||
subtitle +=
|
||||
"You are about to approve an access request to your patient profile.\nPlease be aware that once approved, ${widget.accessRequests[index].Name} will have access to your profile information until ${widget.accessRequests[index].revoke_date.substring(0, 16).replaceAll("T", " ")}.\nIf you are unsure about an upcoming appointment with ${widget.accessRequests[index].Name}, please contact ${widget.accessRequests[index].contact_no} for clarification before approving this request.\n";
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Update Appointment Access",
|
||||
windowBody: Column(
|
||||
children: [
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Text(
|
||||
subtitle,
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: popUpBodySize,
|
||||
//fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
runSpacing: 10,
|
||||
spacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
updateAccessAPICall(index, "declined");
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Decline",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
updateAccessAPICall(index, "approved");
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Approve",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
onWindowTapClose: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
setState(() {
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
});
|
||||
checkScreenSize();
|
||||
return ListView.separated(
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
separatorBuilder: (BuildContext context, index) {
|
||||
return Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
},
|
||||
itemCount: widget.accessRequests.length,
|
||||
itemBuilder: (context, index) {
|
||||
//final patient = widget.patients[index].id_no.contains(widget.searchString);
|
||||
//print(index);
|
||||
return displayQueue(index);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,765 @@
|
||||
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:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/appointment.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_calendar_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_calendar_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_date_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_time_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class BuildAppointmentList extends StatefulWidget {
|
||||
final bool inWaitingRoom;
|
||||
final TextEditingController titleController;
|
||||
final TextEditingController descriptionIDController;
|
||||
final TextEditingController? patientIdController;
|
||||
final TextEditingController dateController;
|
||||
final TextEditingController timeController;
|
||||
|
||||
const BuildAppointmentList({
|
||||
super.key,
|
||||
required this.inWaitingRoom,
|
||||
required this.titleController,
|
||||
required this.descriptionIDController,
|
||||
required this.patientIdController,
|
||||
required this.dateController,
|
||||
required this.timeController,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildAppointmentList> createState() => _BuildAppointmentListState();
|
||||
}
|
||||
|
||||
class _BuildAppointmentListState extends State<BuildAppointmentList> {
|
||||
String baseAPI = AppEnviroment.baseApiUrl;
|
||||
TextEditingController patientIdController = TextEditingController();
|
||||
TextEditingController dateController = TextEditingController();
|
||||
TextEditingController timeController = TextEditingController();
|
||||
TextEditingController idController = TextEditingController();
|
||||
TextEditingController fnameController = TextEditingController();
|
||||
TextEditingController lnameController = TextEditingController();
|
||||
TextEditingController daysExtensionController = TextEditingController();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
int counter = 0;
|
||||
late double width;
|
||||
late double height;
|
||||
|
||||
void clearControllers() {
|
||||
widget.titleController.clear();
|
||||
widget.descriptionIDController.clear();
|
||||
widget.dateController.clear();
|
||||
widget.timeController.clear();
|
||||
}
|
||||
|
||||
double getPaddingSize() {
|
||||
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
|
||||
return (width / 10);
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
Widget displayAppointment(MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider, int index, double bodyWidth) {
|
||||
List<Appointment> appointmentList = mzansiProfileProvider.personalHome
|
||||
? mihCalendarProvider.personalAppointments!
|
||||
: mihCalendarProvider.businessAppointments!;
|
||||
|
||||
// SAFELY EXTRACT DATE AND TIME
|
||||
String dateTimeString = appointmentList[index].date_time;
|
||||
String timePart = "";
|
||||
String datePart = "";
|
||||
|
||||
if (dateTimeString.contains("T")) {
|
||||
List<String> parts = dateTimeString.split('T');
|
||||
datePart = parts[0];
|
||||
timePart = parts[1].substring(0, 5);
|
||||
} else if (dateTimeString.contains(" ")) {
|
||||
List<String> parts = dateTimeString.split(' ');
|
||||
datePart = parts[0];
|
||||
timePart = parts[1].substring(0, 5);
|
||||
} else {
|
||||
// Fallback if format is unexpected
|
||||
datePart = dateTimeString;
|
||||
timePart = "00:00";
|
||||
}
|
||||
|
||||
String heading =
|
||||
"$timePart - ${appointmentList[index].title.toUpperCase()}";
|
||||
String description = appointmentList[index].description;
|
||||
|
||||
DateTime now = DateTime.now();
|
||||
int hourNow = int.parse(now.toString().split(' ')[1].substring(0, 2));
|
||||
String currentDate =
|
||||
DateTime(now.year, now.month, now.day).toString().split(' ')[0];
|
||||
|
||||
int appointHour = int.parse(timePart.split(':')[0]);
|
||||
|
||||
Color appointmentColor = MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
|
||||
if (currentDate == datePart) {
|
||||
if (appointHour < hourNow) {
|
||||
appointmentColor = MihColors.getGreyColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
} else if (appointHour == hourNow) {
|
||||
appointmentColor = MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
}
|
||||
} else if (DateTime.parse(datePart).isBefore(DateTime.parse(currentDate))) {
|
||||
appointmentColor = MihColors.getGreyColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
}
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 3.0,
|
||||
color: appointmentColor,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(20)),
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
heading,
|
||||
style: TextStyle(
|
||||
color: appointmentColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
subtitle: Text(
|
||||
description,
|
||||
style: TextStyle(
|
||||
color: appointmentColor,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
// SAFELY SET CONTROLLER VALUES
|
||||
setState(() {
|
||||
widget.titleController.text = appointmentList[index].title;
|
||||
widget.descriptionIDController.text =
|
||||
appointmentList[index].description;
|
||||
widget.dateController.text = datePart;
|
||||
widget.timeController.text = timePart;
|
||||
});
|
||||
|
||||
if (widget.inWaitingRoom == false) {
|
||||
appointmentDetailsWindow(
|
||||
mzansiProfileProvider, mihCalendarProvider, index, bodyWidth);
|
||||
} else {
|
||||
waitingRoomAppointmentDetailsWindow(
|
||||
mzansiProfileProvider, mihCalendarProvider, index, bodyWidth);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void appointmentDetailsWindow(MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider, int index, double bodyWidth) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Appointment Details",
|
||||
menuOptions: [
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Edit Appointment",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
appointmentUpdateWindow(mzansiProfileProvider,
|
||||
mihCalendarProvider, index, bodyWidth);
|
||||
},
|
||||
),
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.delete,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Delete Appointment",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
deleteAppointmentConfirmationWindow(
|
||||
mzansiProfileProvider, mihCalendarProvider, index);
|
||||
},
|
||||
),
|
||||
],
|
||||
onWindowTapClose: () {
|
||||
context.pop();
|
||||
clearControllers();
|
||||
},
|
||||
windowBody: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.05)
|
||||
: const EdgeInsets.symmetric(horizontal: 0),
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: widget.titleController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Appointment Title",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: widget.dateController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Date",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: widget.timeController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Time",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: widget.descriptionIDController,
|
||||
multiLineInput: true,
|
||||
height: 250,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Appointment Description",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void waitingRoomAppointmentDetailsWindow(
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider,
|
||||
int index,
|
||||
double bodyWidth) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Appointment Details",
|
||||
menuOptions: [
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Edit Appointment",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
appointmentUpdateWindow(mzansiProfileProvider,
|
||||
mihCalendarProvider, index, bodyWidth);
|
||||
},
|
||||
),
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.delete,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Delete Appointment",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
deleteAppointmentConfirmationWindow(
|
||||
mzansiProfileProvider, mihCalendarProvider, index);
|
||||
},
|
||||
),
|
||||
],
|
||||
onWindowTapClose: () {
|
||||
context.pop();
|
||||
clearControllers();
|
||||
},
|
||||
windowBody: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.05)
|
||||
: const EdgeInsets.symmetric(horizontal: 0),
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: widget.titleController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Appointment Title",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: widget.dateController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Date",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: widget.timeController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Time",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: widget.descriptionIDController,
|
||||
multiLineInput: true,
|
||||
height: 250,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Appointment Description",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
// SizedBox(
|
||||
// // width: 500,
|
||||
// child: MIHTextField(
|
||||
// controller: widget.titleController,
|
||||
// hintText: "Patient ID Number",
|
||||
// editable: false,
|
||||
// required: false,
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void appointmentUpdateWindow(MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider, int index, double bodyWidth) {
|
||||
List<Appointment> appointmentList = mzansiProfileProvider.personalHome
|
||||
? mihCalendarProvider.personalAppointments!
|
||||
: mihCalendarProvider.businessAppointments!;
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Update Appointment",
|
||||
onWindowTapClose: () {
|
||||
setState(() {
|
||||
widget.titleController.text = appointmentList[index].title;
|
||||
widget.descriptionIDController.text =
|
||||
appointmentList[index].description;
|
||||
widget.dateController.text =
|
||||
appointmentList[index].date_time.split('T')[0];
|
||||
widget.timeController.text = appointmentList[index]
|
||||
.date_time
|
||||
.split('T')[1]
|
||||
.substring(0, 5);
|
||||
});
|
||||
context.pop();
|
||||
},
|
||||
windowBody: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.05)
|
||||
: const EdgeInsets.symmetric(horizontal: 0),
|
||||
child: Column(
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: widget.titleController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Appointment Title",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihDateField(
|
||||
controller: widget.dateController,
|
||||
labelText: "Date",
|
||||
required: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTimeField(
|
||||
controller: widget.timeController,
|
||||
labelText: "Time",
|
||||
required: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: widget.descriptionIDController,
|
||||
multiLineInput: true,
|
||||
height: 250,
|
||||
requiredText: true,
|
||||
hintText: "Appointment Description",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Center(
|
||||
child: Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
runSpacing: 10,
|
||||
spacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
updateAppointmentCall(mzansiProfileProvider,
|
||||
mihCalendarProvider, index);
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Update",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
bool isAppointmentInputValid() {
|
||||
if (widget.dateController.text.isEmpty ||
|
||||
widget.timeController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void deleteAppointmentConfirmationWindow(
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider,
|
||||
int index) {
|
||||
MihAlertServices().deleteConfirmationAlert(
|
||||
"This appointment will be deleted permanently from your calendar. Are you certain you want to delete it?",
|
||||
() {
|
||||
deleteAppointmentCall(
|
||||
mzansiProfileProvider, mihCalendarProvider, index);
|
||||
},
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> updateAppointmentCall(
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider,
|
||||
int index) async {
|
||||
int statusCode;
|
||||
if (isAppointmentInputValid()) {
|
||||
List<Appointment> appointmentList = mzansiProfileProvider.personalHome
|
||||
? mihCalendarProvider.personalAppointments!
|
||||
: mihCalendarProvider.businessAppointments!;
|
||||
KenLogger.success("ersonalHome: ${mzansiProfileProvider.personalHome}");
|
||||
if (mzansiProfileProvider.personalHome == true) {
|
||||
statusCode = await MihMzansiCalendarApis.updatePersonalAppointment(
|
||||
mzansiProfileProvider.user!,
|
||||
mzansiProfileProvider.business,
|
||||
null,
|
||||
appointmentList[index].idappointments,
|
||||
widget.titleController.text,
|
||||
widget.descriptionIDController.text,
|
||||
widget.dateController.text,
|
||||
widget.timeController.text,
|
||||
mihCalendarProvider,
|
||||
context,
|
||||
);
|
||||
} else if (mzansiProfileProvider.personalHome == false &&
|
||||
widget.inWaitingRoom == false) {
|
||||
statusCode = await MihMzansiCalendarApis.updateBusinessAppointment(
|
||||
mzansiProfileProvider.user!,
|
||||
mzansiProfileProvider.business,
|
||||
mzansiProfileProvider.businessUser,
|
||||
appointmentList[index].idappointments,
|
||||
widget.titleController.text,
|
||||
widget.descriptionIDController.text,
|
||||
widget.dateController.text,
|
||||
widget.timeController.text,
|
||||
mihCalendarProvider,
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
statusCode = await MihMzansiCalendarApis.updatePatientAppointment(
|
||||
mzansiProfileProvider.user!,
|
||||
mzansiProfileProvider.business,
|
||||
mzansiProfileProvider.businessUser,
|
||||
appointmentList[index].idappointments,
|
||||
widget.titleController.text,
|
||||
widget.descriptionIDController.text,
|
||||
widget.dateController.text,
|
||||
widget.timeController.text,
|
||||
context,
|
||||
);
|
||||
}
|
||||
if (statusCode == 200) {
|
||||
context.pop();
|
||||
context.pop();
|
||||
successPopUp("Successfully Updated Appointment",
|
||||
"You appointment has been successfully updated.");
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteAppointmentCall(
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider,
|
||||
int index) async {
|
||||
List<Appointment> appointmentList = mzansiProfileProvider.personalHome
|
||||
? mihCalendarProvider.personalAppointments!
|
||||
: mihCalendarProvider.businessAppointments!;
|
||||
int statucCode = await MihMzansiCalendarApis.deleteAppointmentAPICall(
|
||||
mzansiProfileProvider.user!,
|
||||
mzansiProfileProvider.personalHome,
|
||||
mzansiProfileProvider.business,
|
||||
mzansiProfileProvider.businessUser,
|
||||
widget.inWaitingRoom,
|
||||
appointmentList[index].idappointments,
|
||||
mihCalendarProvider,
|
||||
context,
|
||||
);
|
||||
if (statucCode == 200) {
|
||||
context.pop();
|
||||
context.pop();
|
||||
clearControllers();
|
||||
// successPopUp("Successfully Deleted Appointment",
|
||||
// "You appointment has been successfully deleted from your calendar.");
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
void successPopUp(String title, String message) {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
title,
|
||||
message,
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
clearControllers();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
bool canEditAppointment(MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider, int index) {
|
||||
List<Appointment> appointmentList = mzansiProfileProvider.personalHome
|
||||
? mihCalendarProvider.personalAppointments!
|
||||
: mihCalendarProvider.businessAppointments!;
|
||||
if (mzansiProfileProvider.personalHome == true &&
|
||||
appointmentList[index].app_id == mzansiProfileProvider.user!.app_id &&
|
||||
appointmentList[index].business_id == "") {
|
||||
return true;
|
||||
} else if (mzansiProfileProvider.personalHome == false &&
|
||||
appointmentList[index].business_id ==
|
||||
mzansiProfileProvider.business!.business_id &&
|
||||
appointmentList[index].app_id.isEmpty) {
|
||||
return true;
|
||||
} else if (mzansiProfileProvider.personalHome == false &&
|
||||
appointmentList[index].business_id ==
|
||||
mzansiProfileProvider.business!.business_id &&
|
||||
appointmentList[index].app_id.isNotEmpty) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
daysExtensionController.dispose();
|
||||
dateController.dispose();
|
||||
timeController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var size = MediaQuery.of(context).size;
|
||||
setState(() {
|
||||
width = size.width;
|
||||
height = size.height;
|
||||
});
|
||||
return Consumer2<MzansiProfileProvider, MihCalendarProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider,
|
||||
Widget? child) {
|
||||
// List<Appointment> appointmentList = mzansiProfileProvider.personalHome
|
||||
// ? mihCalendarProvider.personalAppointments!
|
||||
// : mihCalendarProvider.businessAppointments!;
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: getPaddingSize()),
|
||||
child: ListView.builder(
|
||||
itemCount: mzansiProfileProvider.personalHome
|
||||
? mihCalendarProvider.personalAppointments!.length
|
||||
: mihCalendarProvider.businessAppointments!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return displayAppointment(
|
||||
mzansiProfileProvider, mihCalendarProvider, index, width);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
101
mih_ui/lib/mih_packages/calendar/builder/build_queue_list.dart
Normal file
101
mih_ui/lib/mih_packages/calendar/builder/build_queue_list.dart
Normal file
@@ -0,0 +1,101 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/app_user.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/patient_queue.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
|
||||
class BuildQueueList extends StatefulWidget {
|
||||
final List<PatientQueue> patientQueue;
|
||||
final AppUser signedInUser;
|
||||
|
||||
const BuildQueueList({
|
||||
super.key,
|
||||
required this.patientQueue,
|
||||
required this.signedInUser,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildQueueList> createState() => _BuildQueueListState();
|
||||
}
|
||||
|
||||
class _BuildQueueListState extends State<BuildQueueList> {
|
||||
String baseAPI = AppEnviroment.baseApiUrl;
|
||||
TextEditingController dateController = TextEditingController();
|
||||
TextEditingController timeController = TextEditingController();
|
||||
TextEditingController idController = TextEditingController();
|
||||
TextEditingController fnameController = TextEditingController();
|
||||
TextEditingController lnameController = TextEditingController();
|
||||
TextEditingController daysExtensionController = TextEditingController();
|
||||
int counter = 0;
|
||||
|
||||
Widget displayQueue(int index) {
|
||||
String title = widget.patientQueue[index].business_name.toUpperCase();
|
||||
// widget.patientQueue[index].date_time.split('T')[1].substring(0, 5);
|
||||
String line234 = "";
|
||||
// var nowDate = DateTime.now();
|
||||
// var expireyDate = DateTime.parse(widget.patientQueue[index].revoke_date);
|
||||
|
||||
line234 +=
|
||||
widget.patientQueue[index].date_time.split('T')[1].substring(0, 5);
|
||||
|
||||
return ListTile(
|
||||
title: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
subtitle: RichText(
|
||||
text: TextSpan(
|
||||
text: "Time: $line234",
|
||||
style: DefaultTextStyle.of(context).style,
|
||||
// children: [
|
||||
// TextSpan(text: line5),
|
||||
// accessWithColour,
|
||||
// TextSpan(text: line6),
|
||||
// ]
|
||||
),
|
||||
),
|
||||
onTap: () {},
|
||||
);
|
||||
}
|
||||
|
||||
bool isAccessExpired(String accessType) {
|
||||
if (accessType == "EXPIRED") {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
daysExtensionController.dispose();
|
||||
dateController.dispose();
|
||||
timeController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.separated(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
separatorBuilder: (BuildContext context, index) {
|
||||
return Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
},
|
||||
itemCount: widget.patientQueue.length,
|
||||
itemBuilder: (context, index) {
|
||||
//final patient = widget.patients[index].id_no.contains(widget.searchString);
|
||||
//print(index);
|
||||
|
||||
return displayQueue(index);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
115
mih_ui/lib/mih_packages/calendar/mzansi_calendar.dart
Normal file
115
mih_ui/lib/mih_packages/calendar/mzansi_calendar.dart
Normal file
@@ -0,0 +1,115 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_calendar_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/calendar/package_tools/appointments.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_data_helper_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MzansiCalendar extends StatefulWidget {
|
||||
const MzansiCalendar({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiCalendar> createState() => _MzansiCalendarState();
|
||||
}
|
||||
|
||||
class _MzansiCalendarState extends State<MzansiCalendar> {
|
||||
bool _isLoadingInitialData = true;
|
||||
late final Appointments _appointments;
|
||||
|
||||
Future<void> _loadInitialData() async {
|
||||
setState(() {
|
||||
_isLoadingInitialData = true;
|
||||
});
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
if (mzansiProfileProvider.user == null) {
|
||||
await MihDataHelperServices().loadUserDataOnly(
|
||||
mzansiProfileProvider,
|
||||
);
|
||||
}
|
||||
setState(() {
|
||||
_isLoadingInitialData = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_appointments = Appointments();
|
||||
_loadInitialData();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MihCalendarProvider>(
|
||||
builder: (BuildContext context, MihCalendarProvider calendarProvider,
|
||||
Widget? child) {
|
||||
if (_isLoadingInitialData) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Mihloadingcircle(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: calendarProvider.toolIndex,
|
||||
onIndexChange: (newIndex) {
|
||||
calendarProvider.setToolIndex(newIndex);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.read<MihCalendarProvider>().resetSelectedDay();
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.calendar_month)] = () {
|
||||
context.read<MihCalendarProvider>().setToolIndex(0);
|
||||
};
|
||||
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MihCalendarProvider>().toolIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_appointments,
|
||||
];
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
List<String> toolTitles = [
|
||||
mzansiProfileProvider.personalHome == true ? "Personal" : "Business",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import 'package:go_router/go_router.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_package_components/mih_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MzansiCalendarTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
|
||||
const MzansiCalendarTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiCalendarTile> createState() => _MzansiCalendarTileState();
|
||||
}
|
||||
|
||||
class _MzansiCalendarTileState extends State<MzansiCalendarTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageTile(
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
"mihCalendar",
|
||||
);
|
||||
// Navigator.of(context).pushNamed(
|
||||
// '/calendar',
|
||||
// arguments: widget.arguments,
|
||||
// );
|
||||
},
|
||||
appName: "Calendar",
|
||||
appIcon: Icon(
|
||||
MihIcons.calendar,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: widget.packageSize,
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
484
mih_ui/lib/mih_packages/calendar/package_tools/appointments.dart
Normal file
484
mih_ui/lib/mih_packages/calendar/package_tools/appointments.dart
Normal file
@@ -0,0 +1,484 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_calendar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_calendar_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_calendar_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_date_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_floating_menu.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_time_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/appointment.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/calendar/builder/build_appointment_list.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class Appointments extends StatefulWidget {
|
||||
const Appointments({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<Appointments> createState() => _PatientAccessRequestState();
|
||||
}
|
||||
|
||||
class _PatientAccessRequestState extends State<Appointments> {
|
||||
TextEditingController selectedAppointmentDateController =
|
||||
TextEditingController();
|
||||
final TextEditingController _appointmentTitleController =
|
||||
TextEditingController();
|
||||
final TextEditingController _appointmentDescriptionIDController =
|
||||
TextEditingController();
|
||||
final TextEditingController _appointmentDateController =
|
||||
TextEditingController();
|
||||
final TextEditingController _appointmentTimeController =
|
||||
TextEditingController();
|
||||
|
||||
bool isLoading = true;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
Widget displayAppointmentList(MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider) {
|
||||
List<Appointment> appointmentList = mzansiProfileProvider.personalHome
|
||||
? mihCalendarProvider.personalAppointments!
|
||||
: mihCalendarProvider.businessAppointments!;
|
||||
|
||||
return appointmentList.isNotEmpty
|
||||
? Expanded(
|
||||
child: BuildAppointmentList(
|
||||
inWaitingRoom: false,
|
||||
titleController: _appointmentTitleController,
|
||||
descriptionIDController: _appointmentDescriptionIDController,
|
||||
patientIdController: null,
|
||||
dateController: _appointmentDateController,
|
||||
timeController: _appointmentTimeController,
|
||||
),
|
||||
)
|
||||
: Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.calendar,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"No appointments for ${mihCalendarProvider.selectedDay}",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
Icons.menu,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
" to add an appointment or select a different date"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void addAppointmentWindow(MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider, double width) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Add Appointment",
|
||||
onWindowTapClose: () {
|
||||
context.pop();
|
||||
_appointmentDateController.clear();
|
||||
_appointmentTimeController.clear();
|
||||
_appointmentTitleController.clear();
|
||||
_appointmentDescriptionIDController.clear();
|
||||
},
|
||||
windowBody: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.05)
|
||||
: const EdgeInsets.symmetric(horizontal: 0),
|
||||
child: Column(
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: _appointmentTitleController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Appointment Title",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihDateField(
|
||||
controller: _appointmentDateController,
|
||||
labelText: "Date",
|
||||
required: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTimeField(
|
||||
controller: _appointmentTimeController,
|
||||
labelText: "Time",
|
||||
required: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: _appointmentDescriptionIDController,
|
||||
multiLineInput: true,
|
||||
height: 250,
|
||||
requiredText: true,
|
||||
hintText: "Appointment Description",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
addAppointmentCall(
|
||||
mzansiProfileProvider, mihCalendarProvider);
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Add",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
bool isAppointmentInputValid() {
|
||||
if (_appointmentTitleController.text.isEmpty ||
|
||||
_appointmentDescriptionIDController.text.isEmpty ||
|
||||
_appointmentDateController.text.isEmpty ||
|
||||
_appointmentTimeController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> addAppointmentCall(
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider,
|
||||
) async {
|
||||
if (isAppointmentInputValid()) {
|
||||
int statusCode;
|
||||
if (mzansiProfileProvider.personalHome == false) {
|
||||
statusCode = await MihMzansiCalendarApis.addBusinessAppointment(
|
||||
mzansiProfileProvider.user!,
|
||||
mzansiProfileProvider.business!,
|
||||
mzansiProfileProvider.businessUser!,
|
||||
false,
|
||||
_appointmentTitleController.text,
|
||||
_appointmentDescriptionIDController.text,
|
||||
_appointmentDateController.text,
|
||||
_appointmentTimeController.text,
|
||||
mihCalendarProvider,
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
statusCode = await MihMzansiCalendarApis.addPersonalAppointment(
|
||||
mzansiProfileProvider.user!,
|
||||
_appointmentTitleController.text,
|
||||
_appointmentDescriptionIDController.text,
|
||||
_appointmentDateController.text,
|
||||
_appointmentTimeController.text,
|
||||
mihCalendarProvider,
|
||||
context,
|
||||
);
|
||||
}
|
||||
if (statusCode == 201) {
|
||||
context.pop();
|
||||
successPopUp("Successfully Added Appointment",
|
||||
"You appointment has been successfully added to your calendar.");
|
||||
if (mzansiProfileProvider.personalHome == true) {
|
||||
await MihMzansiCalendarApis.getPersonalAppointments(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
mihCalendarProvider.selectedDay,
|
||||
mihCalendarProvider,
|
||||
);
|
||||
} else {
|
||||
await MihMzansiCalendarApis.getBusinessAppointments(
|
||||
mzansiProfileProvider.business!.business_id,
|
||||
false,
|
||||
mihCalendarProvider.selectedDay,
|
||||
mihCalendarProvider,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
checkforchange();
|
||||
}
|
||||
|
||||
void successPopUp(String title, String message) {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
title,
|
||||
message,
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
setState(() {
|
||||
_appointmentDateController.clear();
|
||||
_appointmentTimeController.clear();
|
||||
_appointmentTitleController.clear();
|
||||
_appointmentDescriptionIDController.clear();
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
String getTitle(MzansiProfileProvider mzansiProfileProvider) {
|
||||
if (mzansiProfileProvider.personalHome == false) {
|
||||
return "Business Appointments";
|
||||
} else {
|
||||
return "Personal Appointments";
|
||||
}
|
||||
}
|
||||
|
||||
void checkforchange() {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
_loadInitialAppointments();
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
if (isLoading) {
|
||||
return const Center(
|
||||
child: Mihloadingcircle(),
|
||||
);
|
||||
}
|
||||
return Consumer2<MzansiProfileProvider, MihCalendarProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MihCalendarProvider mihCalendarProvider,
|
||||
Widget? child) {
|
||||
return Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
MIHCalendar(
|
||||
calendarWidth: 500,
|
||||
rowHeight: 35,
|
||||
setDate: (value) {
|
||||
mihCalendarProvider.setSelectedDay(value);
|
||||
setState(() {
|
||||
selectedAppointmentDateController.text = value;
|
||||
});
|
||||
}),
|
||||
// Divider(
|
||||
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
displayAppointmentList(
|
||||
mzansiProfileProvider,
|
||||
mihCalendarProvider,
|
||||
)
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
right: 10,
|
||||
bottom: 10,
|
||||
child: MihFloatingMenu(
|
||||
icon: Icons.add,
|
||||
animatedIcon: AnimatedIcons.menu_close,
|
||||
children: [
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
label: "Add Appointment",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
addAppointmentWindow(
|
||||
mzansiProfileProvider, mihCalendarProvider, width);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _loadInitialAppointments() async {
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
MihCalendarProvider mihCalendarProvider =
|
||||
context.read<MihCalendarProvider>();
|
||||
if (mzansiProfileProvider.personalHome == false) {
|
||||
await MihMzansiCalendarApis.getBusinessAppointments(
|
||||
mzansiProfileProvider.business!.business_id,
|
||||
false,
|
||||
mihCalendarProvider.selectedDay,
|
||||
mihCalendarProvider,
|
||||
);
|
||||
} else {
|
||||
await MihMzansiCalendarApis.getPersonalAppointments(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
mihCalendarProvider.selectedDay,
|
||||
mihCalendarProvider,
|
||||
);
|
||||
}
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
selectedAppointmentDateController.dispose();
|
||||
_appointmentDateController.dispose();
|
||||
_appointmentTimeController.dispose();
|
||||
_appointmentTitleController.dispose();
|
||||
_appointmentDescriptionIDController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
selectedAppointmentDateController.addListener(checkforchange);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
_loadInitialAppointments();
|
||||
});
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(screenWidth),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/package_tools/mih_forgot_password.dart';
|
||||
|
||||
class MihAuthForgotPassword extends StatefulWidget {
|
||||
const MihAuthForgotPassword({super.key});
|
||||
|
||||
@override
|
||||
State<MihAuthForgotPassword> createState() => _MihAuthForgotPasswordState();
|
||||
}
|
||||
|
||||
class _MihAuthForgotPasswordState extends State<MihAuthForgotPassword> {
|
||||
int _selcetedIndex = 0;
|
||||
late final MihForgotPassword _forgotPassword;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_forgotPassword = MihForgotPassword();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appToolTitles: ["Forgot Password"],
|
||||
appBody: getToolBody(),
|
||||
selectedbodyIndex: _selcetedIndex,
|
||||
onIndexChange: (newValue) {
|
||||
setState(() {
|
||||
_selcetedIndex = newValue;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
extra: true,
|
||||
);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.question_mark_rounded)] = () {
|
||||
setState(() {
|
||||
_selcetedIndex = 0;
|
||||
});
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: _selcetedIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_forgotPassword,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/package_tools/mih_reset_password.dart';
|
||||
|
||||
class MihAuthPasswordReset extends StatefulWidget {
|
||||
final String token;
|
||||
const MihAuthPasswordReset({
|
||||
super.key,
|
||||
required this.token,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihAuthPasswordReset> createState() => _MihAuthPasswordResetState();
|
||||
}
|
||||
|
||||
class _MihAuthPasswordResetState extends State<MihAuthPasswordReset> {
|
||||
int _selcetedIndex = 0;
|
||||
late final MihResetPassword _resetPassword;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_resetPassword = MihResetPassword(token: widget.token);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: ["Reset Password"],
|
||||
selectedbodyIndex: _selcetedIndex,
|
||||
onIndexChange: (newValue) {
|
||||
setState(() {
|
||||
_selcetedIndex = newValue;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget getAction() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 5.0),
|
||||
child: MihPackageAction(
|
||||
icon: const Icon(MihIcons.mihLogo),
|
||||
iconSize: 45,
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
extra: true,
|
||||
);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.password_rounded)] = () {
|
||||
setState(() {
|
||||
_selcetedIndex = 0;
|
||||
});
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: _selcetedIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_resetPassword,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_authentication_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/package_tools/mih_register.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/package_tools/mih_sign_in.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihAuthentication extends StatefulWidget {
|
||||
const MihAuthentication({super.key});
|
||||
|
||||
@override
|
||||
State<MihAuthentication> createState() => _MihAuthenticationState();
|
||||
}
|
||||
|
||||
class _MihAuthenticationState extends State<MihAuthentication> {
|
||||
late final MihSignIn _signIn;
|
||||
late final MihRegister _register;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_signIn = MihSignIn();
|
||||
_register = MihRegister();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: context.watch<MihAuthenticationProvider>().toolIndex,
|
||||
onIndexChange: (newIndex) {
|
||||
context.read<MihAuthenticationProvider>().setToolIndex(newIndex);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_signIn,
|
||||
_register,
|
||||
];
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Sign In",
|
||||
"Create an Account",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.perm_identity)] = () {
|
||||
context.read<MihAuthenticationProvider>().setToolIndex(0);
|
||||
};
|
||||
temp[const Icon(Icons.create)] = () {
|
||||
context.read<MihAuthenticationProvider>().setToolIndex(1);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MihAuthenticationProvider>().toolIndex,
|
||||
);
|
||||
}
|
||||
|
||||
Widget getAction() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 5.0),
|
||||
child: MihPackageAction(
|
||||
icon: const Icon(MihIcons.mihLogo),
|
||||
iconSize: 45,
|
||||
onTap: () {
|
||||
context.goNamed("aboutMih", extra: true);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_authentication_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
|
||||
class MihForgotPassword extends StatefulWidget {
|
||||
const MihForgotPassword({super.key});
|
||||
|
||||
@override
|
||||
State<MihForgotPassword> createState() => _MihForgotPasswordState();
|
||||
}
|
||||
|
||||
class _MihForgotPasswordState extends State<MihForgotPassword> {
|
||||
final emailController = TextEditingController();
|
||||
bool successfulForgotPassword = false;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
bool acceptWarning = false;
|
||||
|
||||
Future<void> submitPasswodReset() async {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
try {
|
||||
var resetPassEmailSent = await MihAuthenticationServices()
|
||||
.forgotPassword(emailController.text);
|
||||
context.pop();
|
||||
if (resetPassEmailSent) {
|
||||
setState(() {
|
||||
successfulForgotPassword = true;
|
||||
});
|
||||
}
|
||||
} on Exception {
|
||||
//loginError();
|
||||
}
|
||||
}
|
||||
|
||||
void prePassResteWarning() {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
"Password Reset Confirmation",
|
||||
"Before you reset your password, please be aware that you'll receive an email with a link to confirm your identity and set a new password. Make sure to check your inbox, including spam or junk folders. If you don't receive the email within a few minutes, please try resending the reset request.",
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
acceptWarning = true;
|
||||
});
|
||||
context.pop();
|
||||
validateInput();
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Continue",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
void resetLinkSentSuccessfully() {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
"Successfully Sent Reset Link",
|
||||
"We've sent a password reset link to your email address. Please check your inbox, including spam or junk folders.\n\nOnce you find the email, click on the link to reset your password.\n\nIf you don't receive the email within a few minutes, please try resending the reset request.\n\nThe reset link will expire after 2 hours",
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
extra: true,
|
||||
);
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
void validateInput() async {
|
||||
if (emailController.text.isEmpty) {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
} else {
|
||||
await submitPasswodReset();
|
||||
if (successfulForgotPassword) {
|
||||
// Navigator.of(context).pushNamedAndRemoveUntil('/', (route) => false);
|
||||
resetLinkSentSuccessfully();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(screenWidth),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return KeyboardListener(
|
||||
focusNode: _focusNode,
|
||||
autofocus: true,
|
||||
onKeyEvent: (event) async {
|
||||
if (event is KeyDownEvent &&
|
||||
event.logicalKey == LogicalKeyboardKey.enter) {
|
||||
validateInput();
|
||||
}
|
||||
},
|
||||
child: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
child: Padding(
|
||||
padding: MzansiInnovationHub.of(context)!.theme.screenType ==
|
||||
"desktop"
|
||||
? EdgeInsets.symmetric(vertical: 25, horizontal: width * 0.2)
|
||||
: EdgeInsets.symmetric(vertical: 25, horizontal: width * 0.075),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
//logo
|
||||
Icon(
|
||||
Icons.lock,
|
||||
size: 100,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
//Heading
|
||||
Text(
|
||||
'Forgot Password',
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: emailController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Email",
|
||||
validator: (value) {
|
||||
return MihValidationServices().validateEmail(value);
|
||||
},
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 20),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
prePassResteWarning();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Reset Password",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_authentication_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
import 'package:supertokens_flutter/supertokens.dart';
|
||||
|
||||
class MihRegister extends StatefulWidget {
|
||||
const MihRegister({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihRegister> createState() => _MihRegisterState();
|
||||
}
|
||||
|
||||
class _MihRegisterState extends State<MihRegister> {
|
||||
final emailController = TextEditingController();
|
||||
final passwordController = TextEditingController();
|
||||
final confirmPasswordController = TextEditingController();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final baseAPI = AppEnviroment.baseApiUrl;
|
||||
|
||||
Future<void> addUserAPICall(String email, String uid) async {
|
||||
//await getOfficeIdByUser(docOfficeIdApiUrl + widget.userEmail);
|
||||
//print(futureDocOfficeId.toString());
|
||||
await MihUserServices().createUser(
|
||||
email,
|
||||
uid,
|
||||
context,
|
||||
);
|
||||
// var response = await http.post(
|
||||
// Uri.parse("$baseAPI/user/insert/"),
|
||||
// headers: <String, String>{
|
||||
// "Content-Type": "application/json; charset=UTF-8"
|
||||
// },
|
||||
// body: jsonEncode(<String, dynamic>{
|
||||
// "email": email,
|
||||
// "app_id": uid,
|
||||
// }),
|
||||
// );
|
||||
// if (response.statusCode == 201) {
|
||||
// Navigator.of(context).pushNamedAndRemoveUntil(
|
||||
// '/',
|
||||
// (route) => false,
|
||||
// arguments: AuthArguments(
|
||||
// true,
|
||||
// true,
|
||||
// ),
|
||||
// );
|
||||
// // signUpSuccess();
|
||||
// // setState(() {
|
||||
// // successfulSignUp = true;
|
||||
// // });
|
||||
// } else {
|
||||
// internetConnectionPopUp();
|
||||
// }
|
||||
}
|
||||
|
||||
Future<void> signUserUp() async {
|
||||
context.read<MzansiProfileProvider>().reset();
|
||||
if (!validEmail()) {
|
||||
MihAlertServices().invalidEmailAlert(context);
|
||||
} else if (passwordController.text != confirmPasswordController.text) {
|
||||
MihAlertServices().passwordMatchAlert(context);
|
||||
} else {
|
||||
//var _backgroundColor = Colors.transparent;
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
try {
|
||||
Uri uri = Uri.parse(
|
||||
"$baseAPI/auth/emailpassword/email/exists?email=${emailController.text}");
|
||||
//print("Here");
|
||||
var response = await http.get(uri);
|
||||
//print(response.body);
|
||||
//print("response 1: ${response.statusCode}");
|
||||
if (response.statusCode == 200) {
|
||||
var userExists = jsonDecode(response.body);
|
||||
if (userExists["exists"]) {
|
||||
Navigator.of(context).pop();
|
||||
MihAlertServices().emailExistsAlert(context);
|
||||
} else {
|
||||
var response2 = await http.post(
|
||||
Uri.parse("$baseAPI/auth/signup"),
|
||||
body:
|
||||
'{"formFields": [{"id": "email","value": "${emailController.text}"}, {"id": "password","value": "${passwordController.text}"}]}',
|
||||
headers: {
|
||||
'Content-type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
"Authorization": "leatucczyixqwkqqdrhayiwzeofkltds"
|
||||
},
|
||||
);
|
||||
//print("response 2: ${response2.statusCode}");
|
||||
if (response2.statusCode == 200) {
|
||||
//print("response 2: ${response2.body}");
|
||||
var userCreated = jsonDecode(response2.body);
|
||||
//print("Created user $userCreated");
|
||||
if (userCreated["status"] == "OK") {
|
||||
//print("Here1");
|
||||
//Creat user in db
|
||||
String uid = await SuperTokens.getUserId();
|
||||
//print("uid: $uid");
|
||||
addUserAPICall(emailController.text, uid);
|
||||
Navigator.of(context).pop();
|
||||
//print("Here1");
|
||||
} else if (userCreated["status"] == "FIELD_ERROR") {
|
||||
Navigator.of(context).pop();
|
||||
MihAlertServices().passwordRequirementAlert(context);
|
||||
} else {
|
||||
Navigator.of(context).pop();
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} on Exception catch (error) {
|
||||
Navigator.of(context).pop();
|
||||
loginError(error.toString());
|
||||
emailController.clear();
|
||||
passwordController.clear();
|
||||
confirmPasswordController.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void submitFormInput() async {
|
||||
await signUserUp();
|
||||
}
|
||||
|
||||
bool validEmail() {
|
||||
String text = emailController.text;
|
||||
var regex = RegExp(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$');
|
||||
return regex.hasMatch(text);
|
||||
}
|
||||
|
||||
void loginError(error) {
|
||||
MihAlertServices().errorAdvancedAlert(
|
||||
"Sign Up Error",
|
||||
"An error occurred while signing up: $error Please try again later.",
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 200,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(screenWidth),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return KeyboardListener(
|
||||
focusNode: _focusNode,
|
||||
autofocus: true,
|
||||
onKeyEvent: (event) async {
|
||||
if (event is KeyDownEvent &&
|
||||
event.logicalKey == LogicalKeyboardKey.enter) {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitFormInput();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: MihSingleChildScroll(
|
||||
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.center,
|
||||
children: [
|
||||
//logo
|
||||
Icon(
|
||||
Icons.lock,
|
||||
size: 100,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
//Heading
|
||||
Text(
|
||||
'Create an Account',
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
//spacer
|
||||
// const SizedBox(height: 20),
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
//email input
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: emailController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Email",
|
||||
autofillHints: const [AutofillHints.email],
|
||||
validator: (value) {
|
||||
return MihValidationServices().validateEmail(value);
|
||||
},
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
//password input
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: passwordController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Password",
|
||||
passwordMode: true,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
validator: (value) {
|
||||
return MihValidationServices().validatePassword(value);
|
||||
},
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: confirmPasswordController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Confirm Password",
|
||||
passwordMode: true,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
validator: (value) {
|
||||
return MihValidationServices().validatePassword(value);
|
||||
},
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 20),
|
||||
// sign up button
|
||||
Center(
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
runAlignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitFormInput();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Create New Account",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context
|
||||
.read<MihAuthenticationProvider>()
|
||||
.setToolIndex(0);
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"I have an account",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
//here
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_authentication_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
|
||||
class MihResetPassword extends StatefulWidget {
|
||||
final String token;
|
||||
const MihResetPassword({
|
||||
super.key,
|
||||
required this.token,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihResetPassword> createState() => _MihResetPasswordState();
|
||||
}
|
||||
|
||||
class _MihResetPasswordState extends State<MihResetPassword> {
|
||||
final passwordController = TextEditingController();
|
||||
final confirmPasswordController = TextEditingController();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
void submitFormInput() async {
|
||||
if (passwordController.text != confirmPasswordController.text) {
|
||||
MihAlertServices().passwordMatchAlert(context);
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
bool successfulResetPassword = await MihAuthenticationServices()
|
||||
.resetPassword(widget.token, passwordController.text);
|
||||
context.pop();
|
||||
if (successfulResetPassword) {
|
||||
resetSuccessfully();
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void resetSuccessfully() {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
"Successfully Reset Password",
|
||||
"Great news! Your password reset is complete. You can now log in to Mzansi Innovation Hub using your new password.",
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
extra: true,
|
||||
);
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(screenWidth),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return KeyboardListener(
|
||||
focusNode: _focusNode,
|
||||
autofocus: true,
|
||||
onKeyEvent: (event) async {
|
||||
if (event is KeyDownEvent &&
|
||||
event.logicalKey == LogicalKeyboardKey.enter) {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitFormInput();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
physics: const BouncingScrollPhysics(),
|
||||
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: [
|
||||
// Text("Token: ${widget.token}"), // For testing purposes only
|
||||
//logo
|
||||
Icon(
|
||||
Icons.lock,
|
||||
size: 100,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
//Heading
|
||||
Text(
|
||||
'Reset Password',
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 25),
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: passwordController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Password",
|
||||
passwordMode: true,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
validator: (value) {
|
||||
return MihValidationServices().validatePassword(value);
|
||||
},
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: confirmPasswordController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Confirm Password",
|
||||
passwordMode: true,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
validator: (value) {
|
||||
return MihValidationServices().validatePassword(value);
|
||||
},
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 25),
|
||||
// sign in button
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitFormInput();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Reset Password",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,506 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_authentication_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_authentication_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_install_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihSignIn extends StatefulWidget {
|
||||
const MihSignIn({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihSignIn> createState() => _MihSignInState();
|
||||
}
|
||||
|
||||
class _MihSignInState extends State<MihSignIn> {
|
||||
final emailController = TextEditingController();
|
||||
final passwordController = TextEditingController();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
bool successfulSignIn = false;
|
||||
bool showProfiles = false;
|
||||
final baseAPI = AppEnviroment.baseApiUrl;
|
||||
late List<MihPackageTile> sandboxProfileList = [];
|
||||
|
||||
//sign user in
|
||||
Future<void> signUserIn() async {
|
||||
context.read<MzansiProfileProvider>().reset();
|
||||
try {
|
||||
successfulSignIn = await MihAuthenticationServices().signUserIn(
|
||||
emailController.text,
|
||||
passwordController.text,
|
||||
context,
|
||||
);
|
||||
if (!successfulSignIn) {
|
||||
MihAlertServices().loginErrorAlert(context);
|
||||
passwordController.clear();
|
||||
}
|
||||
} on Exception {
|
||||
Navigator.of(context).pop();
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
passwordController.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void submitSignInForm() async {
|
||||
await signUserIn();
|
||||
if (successfulSignIn) {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
extra: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void setSandboxProfiles(List<MihPackageTile> tileList) {
|
||||
tileList.add(MihPackageTile(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
emailController.text = "testpatient@mzansi-innovation-hub.co.za";
|
||||
passwordController.text = "Testprofile@1234";
|
||||
});
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitSignInForm();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
appName: "Patient",
|
||||
appIcon: Icon(
|
||||
Icons.perm_identity_rounded,
|
||||
color: getPrim(),
|
||||
size: 200,
|
||||
),
|
||||
iconSize: 200,
|
||||
textColor: getPrim(),
|
||||
authenticateUser: false,
|
||||
));
|
||||
tileList.add(MihPackageTile(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
emailController.text = "testdoctor@mzansi-innovation-hub.co.za";
|
||||
passwordController.text = "Testprofile@1234";
|
||||
});
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitSignInForm();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
appName: "Doctor",
|
||||
appIcon: Icon(
|
||||
Icons.medical_services,
|
||||
color: getPrim(),
|
||||
size: 200,
|
||||
),
|
||||
iconSize: 200,
|
||||
textColor: getPrim(),
|
||||
authenticateUser: false,
|
||||
));
|
||||
//if (AppEnviroment.getEnv() == "Dev") {
|
||||
tileList.add(MihPackageTile(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
emailController.text = "test-business@mzansi-innovation-hub.co.za";
|
||||
passwordController.text = "Testprofile@1234";
|
||||
});
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitSignInForm();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
appName: "Business",
|
||||
appIcon: Icon(
|
||||
Icons.business,
|
||||
color: getPrim(),
|
||||
size: 200,
|
||||
),
|
||||
iconSize: 200,
|
||||
textColor: getPrim(),
|
||||
authenticateUser: false,
|
||||
));
|
||||
tileList.add(MihPackageTile(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
emailController.text = "test@mzansi-innovation-hub.co.za";
|
||||
passwordController.text = "Testprofile@1234";
|
||||
});
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitSignInForm();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
appName: "Test",
|
||||
appIcon: Icon(
|
||||
Icons.warning_amber_rounded,
|
||||
color: getPrim(),
|
||||
size: 200,
|
||||
),
|
||||
iconSize: 200,
|
||||
textColor: getPrim(),
|
||||
authenticateUser: false,
|
||||
));
|
||||
//}
|
||||
}
|
||||
|
||||
Color getPrim() {
|
||||
return MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
}
|
||||
|
||||
Color getSec() {
|
||||
return MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
setState(() {
|
||||
setSandboxProfiles(sandboxProfileList);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(screenWidth),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return KeyboardListener(
|
||||
focusNode: _focusNode,
|
||||
autofocus: true,
|
||||
onKeyEvent: (event) async {
|
||||
if (event is KeyDownEvent &&
|
||||
event.logicalKey == LogicalKeyboardKey.enter) {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitSignInForm();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.2)
|
||||
: EdgeInsets.symmetric(horizontal: width * 0.075),
|
||||
child: AutofillGroup(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.getPlatform() ==
|
||||
"Web",
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
MihInstallServices().installMihTrigger(context);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 150,
|
||||
child: Text(
|
||||
"Install MIH",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
//logo
|
||||
Icon(
|
||||
Icons.lock,
|
||||
size: 100,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
//Heading
|
||||
Text(
|
||||
'Sign In',
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: emailController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Email",
|
||||
autofillHints: const [AutofillHints.email],
|
||||
validator: (value) {
|
||||
return MihValidationServices().validateEmail(value);
|
||||
},
|
||||
),
|
||||
//spacer
|
||||
const SizedBox(height: 10),
|
||||
//password input
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: passwordController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Password",
|
||||
passwordMode: true,
|
||||
autofillHints: const [AutofillHints.password],
|
||||
validator: (value) {
|
||||
// return MihValidationServices().validatePassword(value);
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
SizedBox(
|
||||
// width: 500.0,
|
||||
//height: 100.0,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// Navigator.of(context).pushNamed(
|
||||
// '/forgot-password',
|
||||
// );
|
||||
context.goNamed(
|
||||
'forgotPassword',
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'Forgot Password?',
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
//spacer
|
||||
const SizedBox(height: 20),
|
||||
// sign in button
|
||||
Center(
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
runAlignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitSignInForm();
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Sign In",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context
|
||||
.read<MihAuthenticationProvider>()
|
||||
.setToolIndex(1);
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Create New Account",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
//spacer
|
||||
const SizedBox(height: 35),
|
||||
Visibility(
|
||||
visible: AppEnviroment.getEnv() == "Dev",
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: width,
|
||||
//height: 100.0,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Flexible(
|
||||
flex: 1,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: 10.0),
|
||||
child: Divider(),
|
||||
),
|
||||
),
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: GestureDetector(
|
||||
child: Text(
|
||||
'Use Sandox Profile',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark")),
|
||||
),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
showProfiles = !showProfiles;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
const Flexible(
|
||||
flex: 1,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 10.0),
|
||||
child: Divider(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Center(
|
||||
child: Visibility(
|
||||
visible: showProfiles,
|
||||
child: SizedBox(
|
||||
width: 500,
|
||||
child: Column(
|
||||
//mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
GridView.builder(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemCount: sandboxProfileList.length,
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
mainAxisSpacing: 10,
|
||||
maxCrossAxisExtent: 100),
|
||||
itemBuilder: (context, index) {
|
||||
return sandboxProfileList[index];
|
||||
},
|
||||
),
|
||||
// const SizedBox(height: 10),
|
||||
Text(
|
||||
"NB: These accounts are used for test purposes. Please do not store personal information on these profiles.",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 15.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/arguments.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:pdf/pdf.dart';
|
||||
import 'package:printing/printing.dart';
|
||||
import '../../../mih_package_components/mih_loading_circle.dart';
|
||||
|
||||
class MIHPrintPreview extends StatefulWidget {
|
||||
final PrintPreviewArguments arguments;
|
||||
const MIHPrintPreview({
|
||||
super.key,
|
||||
required this.arguments,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MIHPrintPreview> createState() => _MIHPrintPreviewState();
|
||||
}
|
||||
|
||||
class _MIHPrintPreviewState extends State<MIHPrintPreview> {
|
||||
MihPackageAction getActionButton() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(
|
||||
Icons.close,
|
||||
),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PdfPreview(
|
||||
pdfFileName: widget.arguments.fileName,
|
||||
initialPageFormat: PdfPageFormat.a4,
|
||||
loadingWidget: const Mihloadingcircle(),
|
||||
actions: [getActionButton()],
|
||||
build: (format) => widget.arguments.pdfData,
|
||||
);
|
||||
}
|
||||
}
|
||||
72
mih_ui/lib/mih_packages/mih_file_viewer/mih_fle_viewer.dart
Normal file
72
mih_ui/lib/mih_packages/mih_file_viewer/mih_fle_viewer.dart
Normal file
@@ -0,0 +1,72 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_file_viewer_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mih_file_viewer/package_tools/mih_expanded_file_view.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihFleViewer extends StatefulWidget {
|
||||
const MihFleViewer({super.key});
|
||||
|
||||
@override
|
||||
State<MihFleViewer> createState() => _MihFleViewerState();
|
||||
}
|
||||
|
||||
class _MihFleViewerState extends State<MihFleViewer> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MihFileViewerProvider>(
|
||||
builder: (BuildContext context, MihFileViewerProvider fileViewerProvider,
|
||||
Widget? child) {
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: fileViewerProvider.toolIndex,
|
||||
onIndexChange: (newIndex) {
|
||||
fileViewerProvider.setToolIndex(newIndex);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.fullscreen_exit),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.pop();
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"File Viewer",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.file_present)] = () {
|
||||
context.read<MihFileViewerProvider>().setToolIndex(0);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MihFileViewerProvider>().toolIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
List<Widget> toolBodies = [
|
||||
MihExpandedFileView(),
|
||||
];
|
||||
return toolBodies;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_file_viewer_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:syncfusion_flutter_core/theme.dart';
|
||||
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
|
||||
import "package:universal_html/html.dart" as html;
|
||||
import 'package:fl_downloader/fl_downloader.dart';
|
||||
|
||||
class MihExpandedFileView extends StatefulWidget {
|
||||
const MihExpandedFileView({super.key});
|
||||
|
||||
@override
|
||||
State<MihExpandedFileView> createState() => _MihExpandedFileViewState();
|
||||
}
|
||||
|
||||
class _MihExpandedFileViewState extends State<MihExpandedFileView> {
|
||||
late PdfViewerController pdfViewerController = PdfViewerController();
|
||||
int currentPageCount = 0;
|
||||
int currentPage = 0;
|
||||
double startZoomLevel = 1.0;
|
||||
double zoomOut = 0;
|
||||
int progress = 0;
|
||||
late StreamSubscription progressStream;
|
||||
|
||||
void nativeFileDownload(String fileLink) async {
|
||||
var permission = await FlDownloader.requestPermission();
|
||||
if (permission == StoragePermissionStatus.granted) {
|
||||
try {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
await FlDownloader.download(fileLink);
|
||||
Navigator.of(context).pop();
|
||||
} on Exception catch (error) {
|
||||
Navigator.of(context).pop();
|
||||
print(error);
|
||||
}
|
||||
} else {
|
||||
print("denied");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
double width = size.width;
|
||||
double height = size.height;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width, height),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width, double height) {
|
||||
return Consumer<MihFileViewerProvider>(
|
||||
builder: (BuildContext context, MihFileViewerProvider fileViewerProvider,
|
||||
Widget? child) {
|
||||
bool isPDF =
|
||||
fileViewerProvider.filePath.split(".").last.toLowerCase() == "pdf";
|
||||
return Stack(
|
||||
children: [
|
||||
fileViewerProvider.filePath.split(".").last.toLowerCase() == "pdf"
|
||||
? SizedBox(
|
||||
width: width - zoomOut,
|
||||
height: height - 70,
|
||||
child: SfPdfViewerTheme(
|
||||
data: SfPdfViewerThemeData(
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
child: SfPdfViewer.network(
|
||||
fileViewerProvider.fileLink,
|
||||
controller: pdfViewerController,
|
||||
initialZoomLevel: startZoomLevel,
|
||||
pageSpacing: 2,
|
||||
maxZoomLevel: 5,
|
||||
interactionMode: PdfInteractionMode.pan,
|
||||
onDocumentLoaded: (details) {
|
||||
setState(() {
|
||||
currentPage = pdfViewerController.pageNumber;
|
||||
currentPageCount = pdfViewerController.pageCount;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
: SizedBox(
|
||||
width: width,
|
||||
height: height - 70,
|
||||
child: InteractiveViewer(
|
||||
maxScale: 5.0,
|
||||
//minScale: 0.,
|
||||
child: Image.network(fileViewerProvider.fileLink),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 20.0),
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Material(
|
||||
elevation: 10,
|
||||
shadowColor: Colors.black,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
borderRadius: BorderRadius.circular(25.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(25.0),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (isPDF)
|
||||
IconButton(
|
||||
iconSize: 30,
|
||||
padding: const EdgeInsets.all(0),
|
||||
onPressed: () {
|
||||
pdfViewerController.previousPage();
|
||||
//print(pdfViewerController.);
|
||||
//if (pdfViewerController.pageNumber > 1) {
|
||||
setState(() {
|
||||
currentPage = pdfViewerController.pageNumber;
|
||||
});
|
||||
// }
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
if (isPDF)
|
||||
Text(
|
||||
"$currentPage / $currentPageCount",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
if (isPDF)
|
||||
IconButton(
|
||||
iconSize: 30,
|
||||
padding: const EdgeInsets.all(0),
|
||||
onPressed: () {
|
||||
pdfViewerController.nextPage();
|
||||
//print(pdfViewerController.pageNumber);
|
||||
//if (pdfViewerController.pageNumber < currentPageCount) {
|
||||
setState(() {
|
||||
currentPage = pdfViewerController.pageNumber;
|
||||
});
|
||||
//}
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.arrow_forward,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
if (isPDF)
|
||||
IconButton(
|
||||
iconSize: 30,
|
||||
padding: const EdgeInsets.all(0),
|
||||
onPressed: () {
|
||||
if (zoomOut > 0) {
|
||||
setState(() {
|
||||
zoomOut = zoomOut - 100;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
pdfViewerController.zoomLevel =
|
||||
startZoomLevel + 0.25;
|
||||
startZoomLevel =
|
||||
pdfViewerController.zoomLevel;
|
||||
});
|
||||
}
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.zoom_in,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
if (isPDF)
|
||||
IconButton(
|
||||
iconSize: 30,
|
||||
padding: const EdgeInsets.all(0),
|
||||
onPressed: () {
|
||||
if (pdfViewerController.zoomLevel > 1) {
|
||||
setState(() {
|
||||
pdfViewerController.zoomLevel =
|
||||
startZoomLevel - 0.25;
|
||||
startZoomLevel =
|
||||
pdfViewerController.zoomLevel;
|
||||
});
|
||||
} else {
|
||||
if (zoomOut < (width - 100)) {
|
||||
setState(() {
|
||||
zoomOut = zoomOut + 100;
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.zoom_out,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
// IconButton(
|
||||
// iconSize: 30,
|
||||
// padding: const EdgeInsets.all(0),
|
||||
// onPressed: () {
|
||||
// printDocument();
|
||||
// },
|
||||
// icon: Icon(
|
||||
// Icons.print,
|
||||
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
// ),
|
||||
IconButton(
|
||||
iconSize: 30,
|
||||
padding: const EdgeInsets.all(0),
|
||||
onPressed: () {
|
||||
if (kIsWeb) {
|
||||
html.window.open(
|
||||
fileViewerProvider.fileLink, 'download');
|
||||
} else {
|
||||
nativeFileDownload(
|
||||
fileViewerProvider.fileLink,
|
||||
);
|
||||
}
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.download,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
433
mih_ui/lib/mih_packages/mih_home/components/mih_app_drawer.dart
Normal file
433
mih_ui/lib/mih_packages/mih_home/components/mih_app_drawer.dart
Normal file
@@ -0,0 +1,433 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/about_mih_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_access_controlls_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_authentication_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_banner_ad_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_calculator_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_calendar_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_ai_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_wallet_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/patient_manager_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../main.dart';
|
||||
import 'package:supertokens_flutter/supertokens.dart';
|
||||
|
||||
class MIHAppDrawer extends StatefulWidget {
|
||||
const MIHAppDrawer({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MIHAppDrawer> createState() => _MIHAppDrawerState();
|
||||
}
|
||||
|
||||
class _MIHAppDrawerState extends State<MIHAppDrawer> {
|
||||
final proPicController = TextEditingController();
|
||||
late Widget profilePictureLoaded;
|
||||
|
||||
void resetProviders() {
|
||||
context.read<AboutMihProvider>().reset();
|
||||
context.read<MihAccessControllsProvider>().reset();
|
||||
context.read<MihAuthenticationProvider>().reset();
|
||||
context.read<MihBannerAdProvider>().reset();
|
||||
context.read<MihCalculatorProvider>().reset();
|
||||
context.read<MihCalendarProvider>().reset();
|
||||
context.read<MihMineSweeperProvider>().reset();
|
||||
context.read<MzansiAiProvider>().reset();
|
||||
context.read<MzansiDirectoryProvider>().reset();
|
||||
context.read<MzansiWalletProvider>().reset();
|
||||
context.read<PatientManagerProvider>().reset();
|
||||
}
|
||||
|
||||
Future<bool> signOut() async {
|
||||
await SuperTokens.signOut(completionHandler: (error) {
|
||||
// handle error if any
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
Widget displayProPic(MzansiProfileProvider mzansiProfileProvider) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
if (mzansiProfileProvider.personalHome) {
|
||||
context.goNamed(
|
||||
'mzansiProfileManage',
|
||||
);
|
||||
} else {
|
||||
if (mzansiProfileProvider.business == null) {
|
||||
context.goNamed(
|
||||
'businessProfileSetup',
|
||||
extra: mzansiProfileProvider.user,
|
||||
);
|
||||
} else {
|
||||
context.goNamed(
|
||||
"businessProfileManage",
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: MihCircleAvatar(
|
||||
imageFile: mzansiProfileProvider.personalHome
|
||||
? mzansiProfileProvider.userProfilePicture
|
||||
: mzansiProfileProvider.businessProfilePicture,
|
||||
width: 60,
|
||||
editable: false,
|
||||
fileNameController: proPicController,
|
||||
onChange: (_) {},
|
||||
userSelectedfile: null,
|
||||
frameColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
backgroundColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
proPicController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// precacheImage(
|
||||
// MzansiInnovationHub.of(context)!.theme.logoImage().image, context);
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return SafeArea(
|
||||
child: Drawer(
|
||||
//backgroundColor: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return Stack(
|
||||
//fit: StackFit.passthrough,
|
||||
children: [
|
||||
Column(
|
||||
// reverse: false,
|
||||
// padding: EdgeInsets.zero,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
DrawerHeader(
|
||||
decoration: BoxDecoration(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
child: SizedBox(
|
||||
// height: 300,
|
||||
width: constraints.maxWidth,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
displayProPic(mzansiProfileProvider),
|
||||
Visibility(
|
||||
visible: !mzansiProfileProvider.personalHome,
|
||||
child: Text(
|
||||
mzansiProfileProvider.business?.Name ??
|
||||
"Setup Business",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: mzansiProfileProvider.personalHome,
|
||||
child: Text(
|
||||
"${mzansiProfileProvider.user!.fname} ${mzansiProfileProvider.user!.lname}",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: !mzansiProfileProvider.personalHome,
|
||||
child: Text(
|
||||
mzansiProfileProvider.business?.type ?? "",
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: mzansiProfileProvider.personalHome,
|
||||
child: Text(
|
||||
"@${mzansiProfileProvider.user!.username}",
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
mzansiProfileProvider.user!.type
|
||||
.toUpperCase(),
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// ListTile(
|
||||
// title: Row(
|
||||
// mainAxisSize: MainAxisSize.max,
|
||||
// children: [
|
||||
// Icon(
|
||||
// Icons.home_outlined,
|
||||
// color:
|
||||
// MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
// const SizedBox(width: 25.0),
|
||||
// Text(
|
||||
// "Home",
|
||||
// style: TextStyle(
|
||||
// //fontWeight: FontWeight.bold,
|
||||
// color: MzansiInnovationHub.of(context)!
|
||||
// .theme
|
||||
// .secondaryColor(),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// onTap: () {
|
||||
// Navigator.of(context)
|
||||
// .pushNamedAndRemoveUntil('/', (route) => false);
|
||||
// },
|
||||
// ),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
ListTile(
|
||||
title: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.policy,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(width: 25.0),
|
||||
Text(
|
||||
"Privacy Policy",
|
||||
style: TextStyle(
|
||||
//fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
WidgetsBinding.instance
|
||||
.addPostFrameCallback((_) async {
|
||||
context
|
||||
.read<AboutMihProvider>()
|
||||
.setToolIndex(1);
|
||||
});
|
||||
context.goNamed(
|
||||
"aboutMih",
|
||||
extra: true,
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.design_services_rounded,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(width: 25.0),
|
||||
Text(
|
||||
"Terms of Service",
|
||||
style: TextStyle(
|
||||
//fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
WidgetsBinding.instance
|
||||
.addPostFrameCallback((_) async {
|
||||
context
|
||||
.read<AboutMihProvider>()
|
||||
.setToolIndex(2);
|
||||
});
|
||||
context.goNamed(
|
||||
"aboutMih",
|
||||
extra: true,
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.logout,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(width: 25.0),
|
||||
Text(
|
||||
"Sign Out",
|
||||
style: TextStyle(
|
||||
//fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () async {
|
||||
await SuperTokens.signOut(
|
||||
completionHandler: (error) {
|
||||
print(error);
|
||||
});
|
||||
if (await SuperTokens.doesSessionExist() ==
|
||||
false) {
|
||||
resetProviders();
|
||||
await Future.delayed(Duration.zero);
|
||||
if (context.mounted) {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
top: 5,
|
||||
right: 5,
|
||||
width: 30,
|
||||
height: 30,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
// setState(() {
|
||||
// if (MzansiInnovationHub.of(context)?.theme.mode ==
|
||||
// "Dark") {
|
||||
// //darkm = !darkm;
|
||||
// MzansiInnovationHub.of(context)!
|
||||
// .changeTheme(ThemeMode.light);
|
||||
// //print("Dark Mode: $darkm");
|
||||
// } else {
|
||||
// //darkm = !darkm;
|
||||
// MzansiInnovationHub.of(context)!
|
||||
// .changeTheme(ThemeMode.dark);
|
||||
// //print("Dark Mode: $darkm");
|
||||
// }
|
||||
// // Navigator.of(context).popAndPushNamed('/',);
|
||||
// });
|
||||
context.goNamed("aboutMih");
|
||||
},
|
||||
child: Icon(
|
||||
MihIcons.mihLogo,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
// IconButton(
|
||||
// onPressed: () {
|
||||
// setState(() {
|
||||
// if (MzansiInnovationHub.of(context)?.theme.mode == "Dark") {
|
||||
// //darkm = !darkm;
|
||||
// MzansiInnovationHub.of(context)!.changeTheme(ThemeMode.light);
|
||||
// //print("Dark Mode: $darkm");
|
||||
// } else {
|
||||
// //darkm = !darkm;
|
||||
// MzansiInnovationHub.of(context)!.changeTheme(ThemeMode.dark);
|
||||
// //print("Dark Mode: $darkm");
|
||||
// }
|
||||
// Navigator.of(context).popAndPushNamed('/');
|
||||
// });
|
||||
// },
|
||||
// icon: Icon(
|
||||
// Icons.light_mode,
|
||||
// color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: 35,
|
||||
// ),
|
||||
// ),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
413
mih_ui/lib/mih_packages/mih_home/mih_home.dart
Normal file
413
mih_ui/lib/mih_packages/mih_home/mih_home.dart
Normal file
@@ -0,0 +1,413 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/user_consent.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_scack_bar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/about_mih_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mih_home/components/mih_app_drawer.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mih_home/package_tools/mih_business_home.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mih_home/package_tools/mih_personal_home.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_user_consent_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihHome extends StatefulWidget {
|
||||
const MihHome({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihHome> createState() => _MihHomeState();
|
||||
}
|
||||
|
||||
class _MihHomeState extends State<MihHome> {
|
||||
DateTime latestPrivacyPolicyDate = DateTime.parse("2024-12-01");
|
||||
DateTime latestTermOfServiceDate = DateTime.parse("2024-12-01");
|
||||
bool _isLoadingInitialData = true;
|
||||
late final MihPersonalHome _personalHome;
|
||||
late final MihBusinessHome? _businessHome;
|
||||
|
||||
Future<void> _loadInitialData() async {
|
||||
setState(() {
|
||||
_isLoadingInitialData = true;
|
||||
});
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
|
||||
if (mzansiProfileProvider.user == null) {
|
||||
await MihDataHelperServices().loadUserDataWithBusinessesData(
|
||||
mzansiProfileProvider,
|
||||
);
|
||||
}
|
||||
_personalHome = const MihPersonalHome();
|
||||
_businessHome = mzansiProfileProvider.business != null
|
||||
? MihBusinessHome(isLoading: _isLoadingInitialData)
|
||||
: null;
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isLoadingInitialData = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool showPolicyWindow(UserConsent? userConsent) {
|
||||
if (userConsent == null) {
|
||||
return true;
|
||||
} else {
|
||||
if (userConsent.privacy_policy_accepted
|
||||
.isAfter(latestPrivacyPolicyDate) &&
|
||||
userConsent.terms_of_services_accepted
|
||||
.isAfter(latestTermOfServiceDate)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void createOrUpdateAccpetance(MzansiProfileProvider mzansiProfileProvider) {
|
||||
UserConsent? userConsent = mzansiProfileProvider.userConsent;
|
||||
userConsent != null
|
||||
? MihUserConsentServices()
|
||||
.updateUserConsentStatus(
|
||||
DateTime.now().toIso8601String(),
|
||||
DateTime.now().toIso8601String(),
|
||||
mzansiProfileProvider,
|
||||
context,
|
||||
)
|
||||
.then((value) {
|
||||
if (!mounted) return;
|
||||
if (value == 200) {
|
||||
context.goNamed("mihHome");
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
MihSnackBar(
|
||||
child: Text("Thank you for accepting our Policies"),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
MihSnackBar(
|
||||
child: Text("There was an error, please try again later"),
|
||||
),
|
||||
);
|
||||
}
|
||||
})
|
||||
: MihUserConsentServices()
|
||||
.insertUserConsentStatus(
|
||||
DateTime.now().toIso8601String(),
|
||||
DateTime.now().toIso8601String(),
|
||||
mzansiProfileProvider,
|
||||
context,
|
||||
)
|
||||
.then((value) {
|
||||
if (value == 201) {
|
||||
context.goNamed("mihHome");
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
MihSnackBar(
|
||||
child: Text("Thank you for accepting our Policies"),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
MihSnackBar(
|
||||
child: Text("There was an error, please try again later"),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Widget displayConsentWindow(MzansiProfileProvider mzansiProfileProvider) {
|
||||
return Container(
|
||||
color: Colors.black.withValues(alpha: 0.5),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: null,
|
||||
onWindowTapClose: null,
|
||||
windowBody: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.policy,
|
||||
size: 150,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Welcome to the MIH App",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
),
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"To keep using the MIH app, please take a moment to review and accept our Policies. Our agreements helps us keep things running smoothly and securely.",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
),
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Center(
|
||||
child: Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
WidgetsBinding.instance
|
||||
.addPostFrameCallback((_) async {
|
||||
context.read<AboutMihProvider>().setToolIndex(1);
|
||||
});
|
||||
context.goNamed("aboutMih",
|
||||
extra: mzansiProfileProvider.personalHome);
|
||||
},
|
||||
buttonColor: MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Privacy Policy",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
WidgetsBinding.instance
|
||||
.addPostFrameCallback((_) async {
|
||||
context.read<AboutMihProvider>().setToolIndex(2);
|
||||
});
|
||||
context.goNamed("aboutMih",
|
||||
extra: mzansiProfileProvider.personalHome);
|
||||
},
|
||||
buttonColor: MihColors.getYellowColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Terms of Service",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
DateTime now = DateTime.now();
|
||||
KenLogger.success("Date Time Now: $now");
|
||||
createOrUpdateAccpetance(mzansiProfileProvider);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Accept",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadInitialData();
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Personal",
|
||||
"Business",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
if (_isLoadingInitialData) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Mihloadingcircle(),
|
||||
),
|
||||
);
|
||||
}
|
||||
// bool showConsentWindow =
|
||||
// showPolicyWindow(mzansiProfileProvider.userConsent);
|
||||
return Stack(
|
||||
children: [
|
||||
RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await _loadInitialData();
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(mzansiProfileProvider,
|
||||
mzansiProfileProvider.user!.type != "personal"),
|
||||
appBody: getToolBody(mzansiProfileProvider),
|
||||
appToolTitles: getToolTitle(),
|
||||
actionDrawer: getActionDrawer(),
|
||||
selectedbodyIndex:
|
||||
mzansiProfileProvider.personalHome ? 0 : 1,
|
||||
onIndexChange: (newValue) {
|
||||
mzansiProfileProvider.setPersonalHome(newValue == 0);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (showPolicyWindow(mzansiProfileProvider.userConsent))
|
||||
displayConsentWindow(mzansiProfileProvider),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget getAction() {
|
||||
return Builder(builder: (context) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
ImageProvider<Object>? currentImage;
|
||||
String imageKey;
|
||||
if (mzansiProfileProvider.personalHome) {
|
||||
currentImage = mzansiProfileProvider.userProfilePicture;
|
||||
imageKey = 'user_${mzansiProfileProvider.userProfilePicUrl}';
|
||||
} else {
|
||||
currentImage = mzansiProfileProvider.businessProfilePicture;
|
||||
imageKey =
|
||||
'business_${mzansiProfileProvider.businessProfilePicUrl}';
|
||||
}
|
||||
return MihPackageAction(
|
||||
icon: Padding(
|
||||
padding: const EdgeInsets.only(left: 5.0),
|
||||
child: MihCircleAvatar(
|
||||
key: Key(imageKey),
|
||||
imageFile: currentImage,
|
||||
width: 50,
|
||||
editable: false,
|
||||
fileNameController: null,
|
||||
userSelectedfile: null,
|
||||
// frameColor: frameColor,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onChange: (_) {},
|
||||
),
|
||||
),
|
||||
iconSize: 45,
|
||||
onTap: () {
|
||||
Scaffold.of(context).openDrawer();
|
||||
FocusScope.of(context)
|
||||
.requestFocus(FocusNode()); // Fully unfocus all fields
|
||||
// FocusScope.of(context).unfocus(); // Unfocus any text fields
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
MIHAppDrawer getActionDrawer() {
|
||||
return MIHAppDrawer();
|
||||
}
|
||||
|
||||
MihPackageTools getTools(
|
||||
MzansiProfileProvider mzansiProfileProvider, bool isBusinessUser) {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.person)] = () {
|
||||
mzansiProfileProvider.setPersonalHome(true);
|
||||
};
|
||||
if (isBusinessUser) {
|
||||
temp[const Icon(Icons.business_center)] = () {
|
||||
mzansiProfileProvider.setPersonalHome(false);
|
||||
};
|
||||
}
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: mzansiProfileProvider.personalHome ? 0 : 1,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody(MzansiProfileProvider mzansiProfileProvider) {
|
||||
if (mzansiProfileProvider.business == null) {
|
||||
return [
|
||||
_personalHome,
|
||||
];
|
||||
} else {
|
||||
return [
|
||||
_personalHome,
|
||||
_businessHome!,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
151
mih_ui/lib/mih_packages/mih_home/mih_home_error.dart
Normal file
151
mih_ui/lib/mih_packages/mih_home/mih_home_error.dart
Normal file
@@ -0,0 +1,151 @@
|
||||
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_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MihHomeError extends StatefulWidget {
|
||||
final String errorMessage;
|
||||
const MihHomeError({
|
||||
super.key,
|
||||
required this.errorMessage,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihHomeError> createState() => _MihHomeErrorState();
|
||||
}
|
||||
|
||||
class _MihHomeErrorState extends State<MihHomeError> {
|
||||
int _selcetedIndex = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackage(
|
||||
appActionButton: getErrorAction(),
|
||||
appTools: getErrorTools(),
|
||||
appToolTitles: ["Connection Error"],
|
||||
appBody: getErrorToolBody(widget.errorMessage),
|
||||
selectedbodyIndex: _selcetedIndex,
|
||||
onIndexChange: (newValue) {
|
||||
setState(() {
|
||||
_selcetedIndex = newValue;
|
||||
});
|
||||
//print("Index: $_selcetedIndex");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getErrorAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.refresh),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
extra: true,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getErrorTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.power_off_outlined)] = () {
|
||||
setState(() {
|
||||
_selcetedIndex = 0;
|
||||
});
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: _selcetedIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getErrorToolBody(String error) {
|
||||
List<Widget> toolBodies = [
|
||||
MihPackageToolBody(
|
||||
borderOn: true,
|
||||
bodyItem: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Connection Error",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 35,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.power_off_outlined,
|
||||
size: 150,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
SizedBox(
|
||||
width: 500,
|
||||
child: Text(
|
||||
"Looks like we ran into an issue getting your data.\nPlease check you internet connection and try again.",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
extra: true,
|
||||
);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Refresh",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: SizedBox(
|
||||
width: 500,
|
||||
child: SelectionArea(
|
||||
child: Text(
|
||||
"Error: $error",
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
];
|
||||
return toolBodies;
|
||||
}
|
||||
}
|
||||
150
mih_ui/lib/mih_packages/mih_home/mih_route_error.dart
Normal file
150
mih_ui/lib/mih_packages/mih_home/mih_route_error.dart
Normal file
@@ -0,0 +1,150 @@
|
||||
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_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.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MihRouteError extends StatefulWidget {
|
||||
const MihRouteError({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihRouteError> createState() => _MihRouteErrorState();
|
||||
}
|
||||
|
||||
class _MihRouteErrorState extends State<MihRouteError> {
|
||||
int _selcetedIndex = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackage(
|
||||
appActionButton: getErrorAction(),
|
||||
appTools: getErrorTools(),
|
||||
appToolTitles: ["Invalid Path"],
|
||||
appBody: getErrorToolBody(),
|
||||
selectedbodyIndex: _selcetedIndex,
|
||||
onIndexChange: (newValue) {
|
||||
setState(() {
|
||||
_selcetedIndex = newValue;
|
||||
});
|
||||
//print("Index: $_selcetedIndex");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getErrorAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(MihIcons.mihLogo),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
extra: true,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getErrorTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.link_off_rounded)] = () {
|
||||
setState(() {
|
||||
_selcetedIndex = 0;
|
||||
});
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: _selcetedIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getErrorToolBody() {
|
||||
List<Widget> toolBodies = [
|
||||
MihPackageToolBody(
|
||||
borderOn: true,
|
||||
bodyItem: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Oops! Wrong Turn.",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 35,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.link_off_rounded,
|
||||
size: 150,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: Text(
|
||||
"It looks like you've taken a wrong turn and ended up on a package that doesn't exist within the MIH App.\n\nDon't worry, getting back is easy. Just click the button below or the MIH Logo to return to the correct path.",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
extra: true,
|
||||
);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Back to MIH",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
// const SizedBox(height: 15),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.all(10.0),
|
||||
// child: SizedBox(
|
||||
// width: 500,
|
||||
// child: SelectionArea(
|
||||
// child: Text(
|
||||
// "Error: $error",
|
||||
// textAlign: TextAlign.left,
|
||||
// style: TextStyle(
|
||||
// color: MihColors.getRedColor(
|
||||
// MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
// "Dark"),
|
||||
// fontSize: 15,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
)
|
||||
];
|
||||
return toolBodies;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_search_bar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/arguments.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_ai_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tile/about_mih_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tiles/mih_calculator_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/calendar/package_tiles/mzansi_calendar_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tiles/mzansi_ai_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_setup_business_profile_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/package_tiles/pat_manager_tile.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihBusinessHome extends StatefulWidget {
|
||||
final bool isLoading;
|
||||
const MihBusinessHome({
|
||||
super.key,
|
||||
required this.isLoading,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihBusinessHome> createState() => _MihBusinessHomeState();
|
||||
}
|
||||
|
||||
class _MihBusinessHomeState extends State<MihBusinessHome>
|
||||
with SingleTickerProviderStateMixin {
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
late List<Map<String, Widget>> businessPackagesMap;
|
||||
final ValueNotifier<List<Map<String, Widget>>> searchPackageName =
|
||||
ValueNotifier([]);
|
||||
double packageSize = 200;
|
||||
// late final AnimationController _marqueeController;
|
||||
// late final ScrollController _scrollController;
|
||||
final FocusNode _searchFocusNode = FocusNode();
|
||||
final String maintenanceMsg =
|
||||
"\tHeads up! We're doing maintenance on Thur, 15 May 2025 at 10 PM (CAT). MIH may be unavailable briefly.";
|
||||
|
||||
// void _startMarquee() async {
|
||||
// while (mounted) {
|
||||
// final double maxScroll = _scrollController.position.maxScrollExtent;
|
||||
// await Future.delayed(const Duration(milliseconds: 500));
|
||||
// await _scrollController.animateTo(
|
||||
// maxScroll,
|
||||
// duration: _marqueeController.duration!,
|
||||
// curve: Curves.linear,
|
||||
// );
|
||||
// await Future.delayed(const Duration(milliseconds: 500));
|
||||
// _scrollController.jumpTo(0);
|
||||
// await Future.delayed(const Duration(milliseconds: 500));
|
||||
// }
|
||||
// }
|
||||
|
||||
List<Map<String, Widget>> setNewBusinessUserPackages() {
|
||||
List<Map<String, Widget>> temp = [];
|
||||
temp.add({
|
||||
"Setup Business": MzansiSetupBusinessProfileTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
return temp;
|
||||
}
|
||||
|
||||
List<Map<String, Widget>> setBusinessPackages() {
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
// if (mzansiProfileProvider.user == null ||
|
||||
// mzansiProfileProvider.business == null ||
|
||||
// mzansiProfileProvider.businessUser == null) {
|
||||
// return []; // Return empty list if data isn't ready
|
||||
// }
|
||||
List<Map<String, Widget>> temp = [];
|
||||
if (mzansiProfileProvider.business == null && !widget.isLoading) {
|
||||
temp.add({
|
||||
"Setup Business": MzansiSetupBusinessProfileTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
return temp;
|
||||
}
|
||||
//=============== Biz Profile ===============
|
||||
temp.add({
|
||||
"Business Profile": MzansiBusinessProfileTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Pat Manager ===============
|
||||
temp.add({
|
||||
"Patient Manager": PatManagerTile(
|
||||
arguments: PatManagerArguments(
|
||||
mzansiProfileProvider.user!,
|
||||
false,
|
||||
mzansiProfileProvider.business!,
|
||||
mzansiProfileProvider.businessUser!,
|
||||
),
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Calendar ===============
|
||||
temp.add({
|
||||
"Calendar": MzansiCalendarTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Mzansi Directory ===============
|
||||
temp.add({
|
||||
"Mzansi Directory": MzansiDirectoryTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Calculator ===============
|
||||
temp.add({
|
||||
"Calculator": MihCalculatorTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Mzansi AI ===============
|
||||
temp.add({
|
||||
"Mzansi AI": MzansiAiTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== About MIH ===============
|
||||
temp.add({
|
||||
"About MIH": AboutMihTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
return temp;
|
||||
}
|
||||
|
||||
EdgeInsets getPadding(double width, double height) {
|
||||
if (MzansiInnovationHub.of(context)!.theme.screenType == "mobile") {
|
||||
double mobilePadding = 10;
|
||||
return EdgeInsets.only(
|
||||
left: mobilePadding,
|
||||
right: mobilePadding,
|
||||
bottom: mobilePadding,
|
||||
);
|
||||
} else {
|
||||
return EdgeInsets.only(
|
||||
left: width / 13,
|
||||
right: width / 13,
|
||||
bottom: height / 15,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void searchPackage() {
|
||||
if (searchController.text.isEmpty) {
|
||||
searchPackageName.value = businessPackagesMap;
|
||||
} else {
|
||||
List<Map<String, Widget>> temp = [];
|
||||
for (var item in businessPackagesMap) {
|
||||
if (item.keys.first.toLowerCase().contains(searchController.text)) {
|
||||
temp.add(item);
|
||||
}
|
||||
}
|
||||
searchPackageName.value = temp;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
searchController.removeListener(searchPackage);
|
||||
searchController.dispose();
|
||||
// _marqueeController.dispose();
|
||||
// _scrollController.dispose();
|
||||
_searchFocusNode.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
searchController.addListener(searchPackage);
|
||||
|
||||
businessPackagesMap = setBusinessPackages();
|
||||
searchPackage();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
final double width = size.width;
|
||||
final double height = size.height;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width, height),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width, double height) {
|
||||
return Consumer2<MzansiProfileProvider, MzansiAiProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MzansiAiProvider mzansiAiProvider,
|
||||
Widget? child) {
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: Visibility(
|
||||
visible: mzansiProfileProvider.business != null,
|
||||
child: MihSearchBar(
|
||||
controller: searchController,
|
||||
hintText: "Ask Mzansi",
|
||||
prefixIcon: Icons.search,
|
||||
prefixAltIcon: MihIcons.mzansiAi,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
hintColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onPrefixIconTap: () {
|
||||
mzansiAiProvider.ollamaProvider.resetChat();
|
||||
if (searchController.text.isNotEmpty) {
|
||||
mzansiAiProvider
|
||||
.setStartUpQuestion(searchController.text);
|
||||
}
|
||||
context.goNamed("mzansiAi");
|
||||
searchController.clear();
|
||||
},
|
||||
searchFocusNode: _searchFocusNode,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: searchPackageName,
|
||||
builder: (context, value, child) {
|
||||
List<Widget> filteredPackages = value
|
||||
.where((package) => package.keys.first
|
||||
.toLowerCase()
|
||||
.contains(searchController.text.toLowerCase()))
|
||||
.map((package) => package.values.first)
|
||||
.toList();
|
||||
if (filteredPackages.isNotEmpty) {
|
||||
return GridView.builder(
|
||||
padding: getPadding(width, height),
|
||||
itemCount: filteredPackages.length,
|
||||
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: packageSize,
|
||||
crossAxisSpacing: 5,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
return filteredPackages[index];
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.mzansiAi,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Mzansi AI is here to help you!",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/Example/package_tiles/test_package_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_search_bar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_ai_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tile/about_mih_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/access_review/package_tile/mih_access_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/calculator/package_tiles/mih_calculator_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/calendar/package_tiles/mzansi_calendar_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/package_tiles/mih_mine_sweeper_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tiles/mzansi_ai_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_profile_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tiles/mzansi_setup_profile_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/package_tiles/mih_wallet_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/package_tiles/patient_profile_tile.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihPersonalHome extends StatefulWidget {
|
||||
const MihPersonalHome({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihPersonalHome> createState() => _MihPersonalHomeState();
|
||||
}
|
||||
|
||||
class _MihPersonalHomeState extends State<MihPersonalHome>
|
||||
with SingleTickerProviderStateMixin {
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
late List<Map<String, Widget>> personalPackagesMap;
|
||||
final ValueNotifier<List<Map<String, Widget>>> searchPackageName =
|
||||
ValueNotifier([]);
|
||||
double packageSize = 200;
|
||||
// late final AnimationController _marqueeController;
|
||||
// late final ScrollController _scrollController;
|
||||
final FocusNode _searchFocusNode = FocusNode();
|
||||
final String maintenanceMsg =
|
||||
"\tHeads up! We're doing maintenance on Thur, 15 May 2025 at 10 PM (CAT). MIH may be unavailable briefly.";
|
||||
|
||||
// void _startMarquee() async {
|
||||
// while (mounted) {
|
||||
// final double maxScroll = _scrollController.position.maxScrollExtent;
|
||||
// await Future.delayed(const Duration(milliseconds: 500));
|
||||
// await _scrollController.animateTo(
|
||||
// maxScroll,
|
||||
// duration: _marqueeController.duration!,
|
||||
// curve: Curves.linear,
|
||||
// );
|
||||
// await Future.delayed(const Duration(milliseconds: 500));
|
||||
// _scrollController.jumpTo(0);
|
||||
// await Future.delayed(const Duration(milliseconds: 500));
|
||||
// }
|
||||
// }
|
||||
|
||||
List<Map<String, Widget>> setNerUserPersonalPackage() {
|
||||
List<Map<String, Widget>> temp = [];
|
||||
temp.add({
|
||||
"Setup Profile": MzansiSetupProfileTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
return temp;
|
||||
}
|
||||
|
||||
List<Map<String, Widget>> setPersonalPackagesMap() {
|
||||
List<Map<String, Widget>> temp = [];
|
||||
//=============== Mzansi Profile ===============
|
||||
temp.add({
|
||||
"Mzansi Profile": MzansiProfileTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Mzansi Wallet ===============
|
||||
temp.add({
|
||||
"Mzansi Wallet": MihWalletTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Patient Profile ===============
|
||||
temp.add({
|
||||
"Patient Profile": PatientProfileTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Mzansi Directory ===============
|
||||
temp.add({
|
||||
"Mzansi Directory": MzansiDirectoryTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Calendar ===============
|
||||
temp.add({
|
||||
"Calendar": MzansiCalendarTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Mzansi AI ===============
|
||||
temp.add({
|
||||
"Mzansi AI": MzansiAiTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Calculator ===============
|
||||
temp.add({
|
||||
"Calculator": MihCalculatorTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Mine Sweeper ===============
|
||||
temp.add({
|
||||
"Mine Sweeper": MihMineSweeperTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== MIH Access ===============
|
||||
temp.add({
|
||||
"MIH Access": MihAccessTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== About MIH ===============
|
||||
temp.add({
|
||||
"About MIH": AboutMihTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
//=============== Dev ===============
|
||||
if (AppEnviroment.getEnv() == "Dev") {
|
||||
temp.add({
|
||||
"test": TestPackageTile(
|
||||
packageSize: packageSize,
|
||||
)
|
||||
});
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
EdgeInsets getPadding(double width, double height) {
|
||||
if (MzansiInnovationHub.of(context)!.theme.screenType == "mobile") {
|
||||
double mobilePadding = 10;
|
||||
return EdgeInsets.only(
|
||||
left: mobilePadding,
|
||||
right: mobilePadding,
|
||||
bottom: mobilePadding,
|
||||
);
|
||||
} else {
|
||||
return EdgeInsets.only(
|
||||
left: width / 13,
|
||||
right: width / 13,
|
||||
bottom: height / 15,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void searchPackage() {
|
||||
if (searchController.text.isEmpty) {
|
||||
searchPackageName.value = personalPackagesMap;
|
||||
} else {
|
||||
List<Map<String, Widget>> temp = [];
|
||||
for (var item in personalPackagesMap) {
|
||||
if (item.keys.first.toLowerCase().contains(searchController.text)) {
|
||||
temp.add(item);
|
||||
}
|
||||
}
|
||||
searchPackageName.value = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void autoNavToProfile() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.goNamed(
|
||||
'mzansiProfileManage',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
searchController.removeListener(searchPackage);
|
||||
searchController.dispose();
|
||||
_searchFocusNode.dispose();
|
||||
// _marqueeController.dispose();
|
||||
// _scrollController.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
searchController.addListener(searchPackage);
|
||||
MzansiProfileProvider profileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
if (profileProvider.user!.username == "") {
|
||||
personalPackagesMap = setNerUserPersonalPackage();
|
||||
autoNavToProfile();
|
||||
} else {
|
||||
personalPackagesMap = setPersonalPackagesMap();
|
||||
}
|
||||
searchPackage();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
final double width = size.width;
|
||||
final double height = size.height;
|
||||
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width, height),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width, double height) {
|
||||
return Consumer2<MzansiProfileProvider, MzansiAiProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
MzansiAiProvider mzansiAiProvider, Widget? child) {
|
||||
return Column(
|
||||
children: [
|
||||
Visibility(
|
||||
visible: profileProvider.user!.username != "",
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: MihSearchBar(
|
||||
controller: searchController,
|
||||
hintText: "Ask Mzansi",
|
||||
prefixIcon: Icons.search,
|
||||
prefixAltIcon: MihIcons.mzansiAi,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
hintColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onPrefixIconTap: () {
|
||||
mzansiAiProvider.ollamaProvider.resetChat();
|
||||
if (searchController.text.isNotEmpty) {
|
||||
mzansiAiProvider
|
||||
.setStartUpQuestion(searchController.text);
|
||||
}
|
||||
context.goNamed("mzansiAi");
|
||||
searchController.clear();
|
||||
},
|
||||
searchFocusNode: _searchFocusNode,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: searchPackageName,
|
||||
builder: (context, value, child) {
|
||||
List<Widget> filteredPackages = value
|
||||
.where((package) => package.keys.first
|
||||
.toLowerCase()
|
||||
.contains(searchController.text.toLowerCase()))
|
||||
.map((package) => package.values.first)
|
||||
.toList();
|
||||
if (filteredPackages.isNotEmpty) {
|
||||
return GridView.builder(
|
||||
padding: getPadding(width, height),
|
||||
itemCount: filteredPackages.length,
|
||||
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: packageSize,
|
||||
crossAxisSpacing: 5,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
return filteredPackages[index];
|
||||
},
|
||||
);
|
||||
} else {
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.mzansiAi,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Mzansi AI is here to help you!",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class BuildMinesweeperLeaderboardList extends StatefulWidget {
|
||||
const BuildMinesweeperLeaderboardList({super.key});
|
||||
|
||||
@override
|
||||
State<BuildMinesweeperLeaderboardList> createState() =>
|
||||
_BuildMinesweeperLeaderboardListState();
|
||||
}
|
||||
|
||||
class _BuildMinesweeperLeaderboardListState
|
||||
extends State<BuildMinesweeperLeaderboardList> {
|
||||
Color getMedalColor(int index) {
|
||||
switch (index) {
|
||||
case (0):
|
||||
return MihColors.getGoldColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
case (1):
|
||||
return MihColors.getSilverColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
case (2):
|
||||
return MihColors.getBronze(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
default:
|
||||
return MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double width = MediaQuery.sizeOf(context).width;
|
||||
return Consumer2<MzansiProfileProvider, MihMineSweeperProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
|
||||
return ListView.separated(
|
||||
separatorBuilder: (BuildContext context, index) {
|
||||
return Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
},
|
||||
itemCount: mineSweeperProvider.leaderboard!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return FutureBuilder(
|
||||
future: mineSweeperProvider.leaderboardUserPicturesUrl[index],
|
||||
builder: (context, asyncSnapshot) {
|
||||
ImageProvider<Object>? imageFile;
|
||||
bool loading = true;
|
||||
if (asyncSnapshot.connectionState == ConnectionState.done) {
|
||||
loading = false;
|
||||
if (asyncSnapshot.hasData) {
|
||||
imageFile = asyncSnapshot.requireData != ""
|
||||
? CachedNetworkImageProvider(
|
||||
asyncSnapshot.requireData)
|
||||
: null;
|
||||
} else {
|
||||
imageFile = null;
|
||||
}
|
||||
} else {
|
||||
imageFile = null;
|
||||
}
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"#${index + 1}",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
color: getMedalColor(index),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
loading
|
||||
? Icon(
|
||||
MihIcons.mihRing,
|
||||
size: 80,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
)
|
||||
: imageFile == null
|
||||
? Icon(
|
||||
MihIcons.iDontKnow,
|
||||
size: 80,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
)
|
||||
: MihCircleAvatar(
|
||||
key: UniqueKey(),
|
||||
imageFile: imageFile,
|
||||
width: 80,
|
||||
editable: false,
|
||||
fileNameController: null,
|
||||
userSelectedfile: null,
|
||||
frameColor: getMedalColor(index),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
onChange: () {},
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${mineSweeperProvider.leaderboard![index].username}${profileProvider.user!.username == mineSweeperProvider.leaderboard![index].username ? " (You)" : ""}",
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: getMedalColor(index),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Score: ${mineSweeperProvider.leaderboard![index].game_score}\nTime: ${mineSweeperProvider.leaderboard![index].game_time}",
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
// fontWeight: FontWeight.bold,
|
||||
color: getMedalColor(index),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class BuildMyScoreBoardList extends StatefulWidget {
|
||||
const BuildMyScoreBoardList({super.key});
|
||||
|
||||
@override
|
||||
State<BuildMyScoreBoardList> createState() =>
|
||||
_BuildMinesweeperLeaderboardListState();
|
||||
}
|
||||
|
||||
class _BuildMinesweeperLeaderboardListState
|
||||
extends State<BuildMyScoreBoardList> {
|
||||
Color getMedalColor(int index) {
|
||||
switch (index) {
|
||||
case (0):
|
||||
return MihColors.getGoldColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
case (1):
|
||||
return MihColors.getSilverColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
case (2):
|
||||
return MihColors.getBronze(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
default:
|
||||
return MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double width = MediaQuery.sizeOf(context).width;
|
||||
return Consumer2<MzansiProfileProvider, MihMineSweeperProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
|
||||
return ListView.separated(
|
||||
separatorBuilder: (BuildContext context, index) {
|
||||
return Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
},
|
||||
itemCount: mineSweeperProvider.myScoreboard!.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"#${index + 1}",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
color: getMedalColor(index),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Score: ${mineSweeperProvider.myScoreboard![index].game_score}",
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: getMedalColor(index),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"Time: ${mineSweeperProvider.myScoreboard![index].game_time}",
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
// fontWeight: FontWeight.bold,
|
||||
color: getMedalColor(index),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
class BoardSquare {
|
||||
bool hasBomb;
|
||||
int bombsAround;
|
||||
bool isOpened;
|
||||
bool isFlagged;
|
||||
|
||||
BoardSquare({
|
||||
this.hasBomb = false,
|
||||
this.bombsAround = 0,
|
||||
this.isOpened = false,
|
||||
this.isFlagged = false,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:redacted/redacted.dart';
|
||||
|
||||
class LeaderboardUserRanking extends StatelessWidget {
|
||||
final int index;
|
||||
final String proPicUrl;
|
||||
final String username;
|
||||
final dynamic gameScore;
|
||||
final String gameTime;
|
||||
final bool isCurrentUser;
|
||||
final Future<ImageProvider<Object>?> Function(String) getUserPicture;
|
||||
|
||||
const LeaderboardUserRanking({
|
||||
super.key,
|
||||
required this.index,
|
||||
required this.proPicUrl,
|
||||
required this.username,
|
||||
required this.gameScore,
|
||||
required this.gameTime,
|
||||
required this.isCurrentUser,
|
||||
required this.getUserPicture,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder(
|
||||
future: getUserPicture(proPicUrl),
|
||||
builder: (context, asyncSnapshot) {
|
||||
bool isLoading =
|
||||
asyncSnapshot.connectionState == ConnectionState.waiting;
|
||||
|
||||
KenLogger.success("URL: ${asyncSnapshot.data.toString()}");
|
||||
return ListTile(
|
||||
leading: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"#${index + 1}",
|
||||
style: const TextStyle(
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
MihCircleAvatar(
|
||||
key: ValueKey(asyncSnapshot.data
|
||||
.toString()), // Use ValueKey for stable identity
|
||||
imageFile: asyncSnapshot.data,
|
||||
width: 60,
|
||||
editable: false,
|
||||
fileNameController: null,
|
||||
userSelectedfile: null,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onChange: () {},
|
||||
),
|
||||
],
|
||||
),
|
||||
title: Text(
|
||||
"$username${isCurrentUser ? " (You)" : ""}",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
).redacted(context: context, redact: isLoading),
|
||||
subtitle: Text(
|
||||
"Score: $gameScore\nTime: $gameTime",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
).redacted(context: context, redact: isLoading),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
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_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihMineSweeperStartGameWindow extends StatefulWidget {
|
||||
final void Function()? onPressed;
|
||||
const MihMineSweeperStartGameWindow({
|
||||
super.key,
|
||||
required this.onPressed,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihMineSweeperStartGameWindow> createState() =>
|
||||
_MihMineSweeperStartGameWindowState();
|
||||
}
|
||||
|
||||
class _MihMineSweeperStartGameWindowState
|
||||
extends State<MihMineSweeperStartGameWindow> {
|
||||
TextEditingController modeController = TextEditingController();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
void applyGameSettings(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
mihMineSweeperProvider.setDifficulty(modeController.text);
|
||||
switch (mihMineSweeperProvider.difficulty) {
|
||||
case ("Very Easy"):
|
||||
mihMineSweeperProvider.setRowCount(6);
|
||||
mihMineSweeperProvider.setCoulmnCount(6);
|
||||
mihMineSweeperProvider.setTotalMines(5);
|
||||
// mihMineSweeperProvider.setRowCount(5);
|
||||
// mihMineSweeperProvider.setCoulmnCount(5);
|
||||
// mihMineSweeperProvider.setTotalMines(3);
|
||||
break;
|
||||
case ("Easy"):
|
||||
mihMineSweeperProvider.setRowCount(8);
|
||||
mihMineSweeperProvider.setCoulmnCount(8);
|
||||
mihMineSweeperProvider.setTotalMines(10);
|
||||
// mihMineSweeperProvider.setRowCount(10);
|
||||
// mihMineSweeperProvider.setCoulmnCount(10);
|
||||
// mihMineSweeperProvider.setTotalMines(15);
|
||||
break;
|
||||
case ("Intermediate"):
|
||||
mihMineSweeperProvider.setRowCount(10);
|
||||
mihMineSweeperProvider.setCoulmnCount(10);
|
||||
mihMineSweeperProvider.setTotalMines(18);
|
||||
// mihMineSweeperProvider.setRowCount(15);
|
||||
// mihMineSweeperProvider.setCoulmnCount(10);
|
||||
// mihMineSweeperProvider.setTotalMines(23);
|
||||
break;
|
||||
case ("Hard"):
|
||||
mihMineSweeperProvider.setRowCount(12);
|
||||
mihMineSweeperProvider.setCoulmnCount(10);
|
||||
mihMineSweeperProvider.setTotalMines(30);
|
||||
// mihMineSweeperProvider.setRowCount(20);
|
||||
// mihMineSweeperProvider.setCoulmnCount(10);
|
||||
// mihMineSweeperProvider.setTotalMines(30);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String getModeConfig() {
|
||||
switch (modeController.text) {
|
||||
case ("Very Easy"):
|
||||
return "Columns: 6\nRows: 6\nBombs: 5";
|
||||
case ("Easy"):
|
||||
return "Columns: 8\nRows: 8\nBombs: 10";
|
||||
case ("Intermediate"):
|
||||
return "Columns: 10\nRows: 10\nBombs: 18";
|
||||
case ("Hard"):
|
||||
return "Columns: 10\nRows: 12\nBombs: 30";
|
||||
default:
|
||||
return "Error";
|
||||
}
|
||||
}
|
||||
|
||||
void _onModeChanged() {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
modeController.removeListener(_onModeChanged);
|
||||
modeController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
modeController.text = context.read<MihMineSweeperProvider>().difficulty;
|
||||
modeController.addListener(_onModeChanged);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "New Game Settings",
|
||||
onWindowTapClose: () {
|
||||
context.pop();
|
||||
},
|
||||
windowBody: Consumer<MihMineSweeperProvider>(
|
||||
builder: (BuildContext context,
|
||||
MihMineSweeperProvider mihMineSweeperProvider, Widget? child) {
|
||||
return Column(
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihDropdownField(
|
||||
controller: modeController,
|
||||
hintText: "Difficulty",
|
||||
dropdownOptions: [
|
||||
"Very Easy",
|
||||
"Easy",
|
||||
"Intermediate",
|
||||
"Hard"
|
||||
],
|
||||
requiredText: true,
|
||||
editable: true,
|
||||
enableSearch: false,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
getModeConfig(),
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
applyGameSettings(mihMineSweeperProvider);
|
||||
context.pop();
|
||||
widget.onPressed?.call();
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Start Game",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
112
mih_ui/lib/mih_packages/mine_sweeper/components/mine_tile.dart
Normal file
112
mih_ui/lib/mih_packages/mine_sweeper/components/mine_tile.dart
Normal file
@@ -0,0 +1,112 @@
|
||||
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_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/components/board_square.dart';
|
||||
|
||||
class MineTile extends StatelessWidget {
|
||||
final BoardSquare square;
|
||||
final VoidCallback onTap;
|
||||
final VoidCallback onLongPress;
|
||||
|
||||
const MineTile({
|
||||
super.key,
|
||||
required this.square,
|
||||
required this.onTap,
|
||||
required this.onLongPress,
|
||||
});
|
||||
|
||||
Widget _getTileContent(BuildContext context) {
|
||||
if (square.isFlagged) {
|
||||
return Icon(
|
||||
Icons.flag,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (square.isOpened) {
|
||||
if (square.hasBomb) {
|
||||
return const Icon(FontAwesomeIcons.bomb, color: Colors.black);
|
||||
} else if (square.bombsAround > 0) {
|
||||
// Display bomb count
|
||||
return Center(
|
||||
child: Text(
|
||||
'${square.bombsAround}',
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: _getTileColor(square.bombsAround, context),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
// Opened, but no bomb count (empty square)
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
|
||||
// Default: Unopened tile
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
Color _getTileColor(int bombsAround, BuildContext context) {
|
||||
// Choose colors based on standard Minesweeper appearance
|
||||
switch (bombsAround) {
|
||||
case 1:
|
||||
return MihColors.getBluishPurpleColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark",
|
||||
);
|
||||
// return Colors.blue;
|
||||
case 2:
|
||||
return MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark",
|
||||
);
|
||||
// return Colors.green;
|
||||
case 3:
|
||||
return MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark",
|
||||
);
|
||||
// return Colors.red;
|
||||
case 4:
|
||||
return MihColors.getPurpleColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark",
|
||||
);
|
||||
// return Colors.purple;
|
||||
case 5:
|
||||
return MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark",
|
||||
);
|
||||
// return Colors.brown;
|
||||
default:
|
||||
// return MihColors.getBluishPurpleColor(
|
||||
// MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
// );
|
||||
return Colors.black;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(1.0),
|
||||
child: MihButton(
|
||||
onPressed: onTap,
|
||||
onLongPressed: onLongPress,
|
||||
buttonColor: square.isOpened
|
||||
? MihColors.getGreyColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
)
|
||||
: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
),
|
||||
width: 50,
|
||||
height: 50,
|
||||
borderRadius: 3,
|
||||
child: _getTileContent(context),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
141
mih_ui/lib/mih_packages/mine_sweeper/mih_mine_sweeper.dart
Normal file
141
mih_ui/lib/mih_packages/mine_sweeper/mih_mine_sweeper.dart
Normal file
@@ -0,0 +1,141 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_banner_ad_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/package_tools/mih_mine_sweeper_leader_board.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/package_tools/mine_sweeper_game.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/package_tools/mine_sweeper_quick_start_guide.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/package_tools/my_score_board.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_data_helper_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihMineSweeper extends StatefulWidget {
|
||||
const MihMineSweeper({super.key});
|
||||
|
||||
@override
|
||||
State<MihMineSweeper> createState() => _MihMineSweeperState();
|
||||
}
|
||||
|
||||
class _MihMineSweeperState extends State<MihMineSweeper> {
|
||||
bool _isLoadingInitialData = true;
|
||||
late final MineSweeperGame _mineSweeperGame;
|
||||
late final MihMineSweeperLeaderBoard _mineSweeperLeaderBoard;
|
||||
late final MyScoreBoard _myScoreBoard;
|
||||
late final MineSweeperQuickStartGuide _mineSweeperQuickStartGuide;
|
||||
|
||||
Future<void> _loadInitialData() async {
|
||||
setState(() {
|
||||
_isLoadingInitialData = true;
|
||||
});
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
MihBannerAdProvider bannerAdProvider = context.read<MihBannerAdProvider>();
|
||||
if (mzansiProfileProvider.user == null) {
|
||||
await MihDataHelperServices().loadUserDataOnly(
|
||||
mzansiProfileProvider,
|
||||
);
|
||||
}
|
||||
bannerAdProvider.loadBannerAd();
|
||||
setState(() {
|
||||
_isLoadingInitialData = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_mineSweeperGame = MineSweeperGame();
|
||||
_mineSweeperLeaderBoard = MihMineSweeperLeaderBoard();
|
||||
_myScoreBoard = MyScoreBoard();
|
||||
_mineSweeperQuickStartGuide = MineSweeperQuickStartGuide();
|
||||
_loadInitialData();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MihMineSweeperProvider>(
|
||||
builder:
|
||||
(BuildContext context, MihMineSweeperProvider value, Widget? child) {
|
||||
if (_isLoadingInitialData) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Mihloadingcircle(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appToolTitles: getToolTitle(),
|
||||
appBody: getToolBody(),
|
||||
selectedbodyIndex: context.watch<MihMineSweeperProvider>().toolIndex,
|
||||
onIndexChange: (newIndex) {
|
||||
context.read<MihMineSweeperProvider>().setToolIndex(newIndex);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
MihMineSweeperProvider mineSweeperProvider =
|
||||
context.read<MihMineSweeperProvider>();
|
||||
mineSweeperProvider.setToolIndex(0);
|
||||
mineSweeperProvider.setDifficulty("Easy");
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(FontAwesomeIcons.bomb)] = () {
|
||||
context.read<MihMineSweeperProvider>().setToolIndex(0);
|
||||
};
|
||||
temp[const Icon(Icons.leaderboard_rounded)] = () {
|
||||
context.read<MihMineSweeperProvider>().setToolIndex(1);
|
||||
};
|
||||
temp[const Icon(Icons.perm_identity_rounded)] = () {
|
||||
context.read<MihMineSweeperProvider>().setToolIndex(2);
|
||||
};
|
||||
temp[const Icon(Icons.rule_rounded)] = () {
|
||||
context.read<MihMineSweeperProvider>().setToolIndex(3);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MihMineSweeperProvider>().toolIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Minesweeper",
|
||||
"Leader Board",
|
||||
"My Scores",
|
||||
"Guide",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_mineSweeperGame,
|
||||
_mineSweeperLeaderBoard,
|
||||
_myScoreBoard,
|
||||
_mineSweeperQuickStartGuide,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
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_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MihMineSweeperTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
const MihMineSweeperTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihMineSweeperTile> createState() => _MihMineSweeperTileState();
|
||||
}
|
||||
|
||||
class _MihMineSweeperTileState extends State<MihMineSweeperTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageTile(
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
"mihMinesweeper",
|
||||
);
|
||||
},
|
||||
appName: "Minesweeper",
|
||||
appIcon: Icon(
|
||||
MihIcons.mineSweeper,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: widget.packageSize,
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/builders/build_minesweeper_leaderboard_list.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_minesweeper_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihMineSweeperLeaderBoard extends StatefulWidget {
|
||||
const MihMineSweeperLeaderBoard({super.key});
|
||||
|
||||
@override
|
||||
State<MihMineSweeperLeaderBoard> createState() =>
|
||||
_MihMineSweeperLeaderBoardState();
|
||||
}
|
||||
|
||||
class _MihMineSweeperLeaderBoardState extends State<MihMineSweeperLeaderBoard> {
|
||||
TextEditingController filterController = TextEditingController();
|
||||
bool isLoading = true;
|
||||
Future<void> initialiseLeaderboard() async {
|
||||
MihMineSweeperProvider mineSweeperProvider =
|
||||
context.read<MihMineSweeperProvider>();
|
||||
filterController.text = mineSweeperProvider.difficulty;
|
||||
KenLogger.success("getting data");
|
||||
await MihMinesweeperServices().getTop20Leaderboard(mineSweeperProvider);
|
||||
List<Future<String>> userPicturesUrl = [];
|
||||
Future<String> userPicUrl;
|
||||
for (final ranking in mineSweeperProvider.leaderboard!) {
|
||||
userPicUrl = MihFileApi.getMinioFileUrl(ranking.proPicUrl);
|
||||
userPicturesUrl.add(userPicUrl);
|
||||
}
|
||||
mineSweeperProvider.setLeaderboardUserPictures(
|
||||
leaderboardUserPicturesUrl: userPicturesUrl);
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
void refreshLeaderBoard(
|
||||
MihMineSweeperProvider mineSweeperProvider, String difficulty) {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
mineSweeperProvider.setDifficulty(difficulty);
|
||||
mineSweeperProvider.setLeaderboard(leaderboard: null);
|
||||
mineSweeperProvider.setMyScoreboard(myScoreboard: null);
|
||||
initialiseLeaderboard();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await initialiseLeaderboard();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double width = MediaQuery.sizeOf(context).width;
|
||||
return Consumer<MihMineSweeperProvider>(
|
||||
builder: (BuildContext context,
|
||||
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
refreshLeaderBoard(mineSweeperProvider, filterController.text);
|
||||
},
|
||||
child: MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return Consumer<MihMineSweeperProvider>(
|
||||
builder: (BuildContext context,
|
||||
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
|
||||
if (isLoading) {
|
||||
return Center(
|
||||
child: Mihloadingcircle(),
|
||||
);
|
||||
} else {
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
child: MihDropdownField(
|
||||
controller: filterController,
|
||||
hintText: "Leaderboards",
|
||||
dropdownOptions: const [
|
||||
"Very Easy",
|
||||
"Easy",
|
||||
"Intermediate",
|
||||
"Hard",
|
||||
],
|
||||
requiredText: true,
|
||||
editable: true,
|
||||
enableSearch: false,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
onSelected: (selection) {
|
||||
refreshLeaderBoard(mineSweeperProvider, selection!);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
!isLoading && mineSweeperProvider.leaderboard!.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.mineSweeper,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Be the first on the leaderboard.",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
FontAwesomeIcons.bomb,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(text: " and start a new game"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Expanded(
|
||||
child: BuildMinesweeperLeaderboardList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,860 @@
|
||||
import 'dart:async';
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:go_router/go_router.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_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_floating_menu.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.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/mih_mine_sweeper_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/components/board_square.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/components/mih_mine_sweeper_start_game_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/components/mine_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_minesweeper_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MineSweeperGame extends StatefulWidget {
|
||||
const MineSweeperGame({super.key});
|
||||
|
||||
@override
|
||||
State<MineSweeperGame> createState() => _MineSweeperGameState();
|
||||
}
|
||||
|
||||
class _MineSweeperGameState extends State<MineSweeperGame> {
|
||||
List<List<BoardSquare>> board = [];
|
||||
bool isGameOver = false;
|
||||
bool isGameWon = false;
|
||||
int squaresLeft = -1;
|
||||
Timer? _timer;
|
||||
int _milliseconds = 0;
|
||||
bool _isRunning = false;
|
||||
static const int millisecondsPerUpdate = 100;
|
||||
|
||||
double timeStringToTotalSeconds(String timeString) {
|
||||
try {
|
||||
List<String> parts = timeString.split(':');
|
||||
if (parts.length != 4) {
|
||||
return 0.0;
|
||||
}
|
||||
double hours = double.parse(parts[0]);
|
||||
double minutes = double.parse(parts[1]);
|
||||
double seconds = double.parse(parts[2]);
|
||||
double milliseconds = double.parse(parts[3]);
|
||||
double totalSeconds =
|
||||
(hours * 3600) + (minutes * 60) + seconds + (milliseconds / 100);
|
||||
return totalSeconds;
|
||||
} catch (e) {
|
||||
print("Error parsing time string: $e");
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
double calculateGameScore(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
int scoreConst = 10000;
|
||||
double dificusltyMultiplier;
|
||||
switch (mihMineSweeperProvider.difficulty) {
|
||||
case ("Very Easy"):
|
||||
dificusltyMultiplier = 0.5;
|
||||
break;
|
||||
case ("Easy"):
|
||||
dificusltyMultiplier = 1.0;
|
||||
break;
|
||||
case ("Intermediate"):
|
||||
dificusltyMultiplier = 2.5;
|
||||
break;
|
||||
case ("Hard"):
|
||||
dificusltyMultiplier = 5.0;
|
||||
break;
|
||||
default:
|
||||
dificusltyMultiplier = 0.0;
|
||||
break;
|
||||
}
|
||||
double rawScore = (scoreConst * dificusltyMultiplier) /
|
||||
timeStringToTotalSeconds(_formatTime());
|
||||
|
||||
String scoreString = rawScore.toStringAsFixed(5);
|
||||
return double.parse(scoreString);
|
||||
}
|
||||
|
||||
void startTimer() {
|
||||
if (_isRunning) return;
|
||||
_isRunning = true;
|
||||
_timer = Timer.periodic(const Duration(milliseconds: millisecondsPerUpdate),
|
||||
(timer) {
|
||||
setState(() {
|
||||
_milliseconds += millisecondsPerUpdate; // Increment by the interval
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void stopTimer() {
|
||||
_timer?.cancel();
|
||||
setState(() {
|
||||
_isRunning = false;
|
||||
});
|
||||
}
|
||||
|
||||
void resetTimer() {
|
||||
stopTimer(); // Stop the timer first
|
||||
setState(() {
|
||||
_milliseconds = 0; // Reset the time to zero
|
||||
});
|
||||
}
|
||||
|
||||
String _formatTime() {
|
||||
Duration duration = Duration(milliseconds: _milliseconds);
|
||||
final int hours = duration.inHours;
|
||||
final int minutes = duration.inMinutes.remainder(60);
|
||||
final int seconds = duration.inSeconds.remainder(60);
|
||||
final int centiseconds = (duration.inMilliseconds.remainder(1000)) ~/ 10;
|
||||
String hoursStr = hours.toString().padLeft(2, '0');
|
||||
String minutesStr = minutes.toString().padLeft(2, '0');
|
||||
String secondsStr = seconds.toString().padLeft(2, '0');
|
||||
String centiStr = centiseconds.toString().padLeft(2, '0');
|
||||
return '$hoursStr:$minutesStr:$secondsStr:$centiStr';
|
||||
}
|
||||
|
||||
void showStartGameWindow(
|
||||
MihMineSweeperProvider mihMineSweeperProvider,
|
||||
) {
|
||||
// easy - 10 * 10 & 15 bombs
|
||||
// Intermediate - 10 * 15 & 23 bombs
|
||||
// Hard - 10 * 20 & 30 bombs
|
||||
showDialog(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MihMineSweeperStartGameWindow(
|
||||
onPressed: () {
|
||||
resetTimer();
|
||||
mihMineSweeperProvider
|
||||
.setDifficulty(mihMineSweeperProvider.difficulty);
|
||||
setState(() => initializeBoard(mihMineSweeperProvider));
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// --- GAME INITIALIZATION LOGIC ---
|
||||
void initializeBoard(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
// 1. Create a board of empty squares
|
||||
board = List.generate(
|
||||
mihMineSweeperProvider.rowCount,
|
||||
(i) => List.generate(
|
||||
mihMineSweeperProvider.columnCount,
|
||||
(j) => BoardSquare(),
|
||||
),
|
||||
);
|
||||
// 2. Place bombs randomly
|
||||
placeBombs(mihMineSweeperProvider);
|
||||
// 3. Calculate the number of bombs around each non-mine square
|
||||
calculateBombsAround(mihMineSweeperProvider);
|
||||
// Reset state variables
|
||||
squaresLeft =
|
||||
mihMineSweeperProvider.rowCount * mihMineSweeperProvider.columnCount;
|
||||
isGameOver = false;
|
||||
isGameWon = false;
|
||||
// You'd typically add a call to setState here, but it's in initState.
|
||||
startTimer();
|
||||
}
|
||||
|
||||
void placeBombs(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
final Random random = Random();
|
||||
int bombsPlaced = 0;
|
||||
|
||||
while (bombsPlaced < mihMineSweeperProvider.totalMines) {
|
||||
int r = random.nextInt(mihMineSweeperProvider.rowCount);
|
||||
int c = random.nextInt(mihMineSweeperProvider.columnCount);
|
||||
|
||||
if (!board[r][c].hasBomb) {
|
||||
board[r][c].hasBomb = true;
|
||||
bombsPlaced++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void calculateBombsAround(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
for (int r = 0; r < mihMineSweeperProvider.rowCount; r++) {
|
||||
for (int c = 0; c < mihMineSweeperProvider.columnCount; c++) {
|
||||
if (!board[r][c].hasBomb) {
|
||||
int count = 0;
|
||||
|
||||
// Check the 8 neighbors
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
if (i == 0 && j == 0) continue; // Skip the current square
|
||||
|
||||
int neighborR = r + i;
|
||||
int neighborC = c + j;
|
||||
|
||||
// Check if neighbor is within bounds
|
||||
if (neighborR >= 0 &&
|
||||
neighborR < mihMineSweeperProvider.rowCount &&
|
||||
neighborC >= 0 &&
|
||||
neighborC < mihMineSweeperProvider.columnCount) {
|
||||
if (board[neighborR][neighborC].hasBomb) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
board[r][c].bombsAround = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handles recursive opening of zero-squares
|
||||
void _expandZeros(
|
||||
MihMineSweeperProvider mihMineSweeperProvider, int r, int c) {
|
||||
if (r < 0 ||
|
||||
r >= mihMineSweeperProvider.rowCount ||
|
||||
c < 0 ||
|
||||
c >= mihMineSweeperProvider.columnCount ||
|
||||
board[r][c].isOpened) {
|
||||
return;
|
||||
}
|
||||
|
||||
BoardSquare square = board[r][c];
|
||||
|
||||
// Open the current square
|
||||
square.isOpened = true;
|
||||
squaresLeft--;
|
||||
|
||||
// If it's a zero square, recursively call for neighbors
|
||||
if (square.bombsAround == 0) {
|
||||
// Check all 8 neighbors (not just 4 sides, for standard Minesweeper expansion)
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
_expandZeros(mihMineSweeperProvider, r + i, c + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> handleTap(MzansiProfileProvider profileProvider,
|
||||
MihMineSweeperProvider mihMineSweeperProvider, int r, int c) async {
|
||||
if (isGameOver || board[r][c].isOpened || board[r][c].isFlagged) {
|
||||
return;
|
||||
}
|
||||
// 1. Check for bomb (LOSS)
|
||||
if (board[r][c].hasBomb) {
|
||||
stopTimer();
|
||||
setState(() {
|
||||
board[r][c].isOpened = true;
|
||||
isGameOver = true;
|
||||
// lose alert
|
||||
loseAlert(mihMineSweeperProvider);
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 2. Open square and handle expansion (RECURSION)
|
||||
if (board[r][c].bombsAround == 0) {
|
||||
// Start recursive expansion
|
||||
_expandZeros(mihMineSweeperProvider, r, c);
|
||||
} else {
|
||||
// Just open the single square
|
||||
board[r][c].isOpened = true;
|
||||
squaresLeft--;
|
||||
}
|
||||
// 3. Check for win
|
||||
_checkWinCondition(profileProvider, mihMineSweeperProvider);
|
||||
// Update the UI
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
void handleLongPress(int r, int c) {
|
||||
if (isGameOver || board[r][c].isOpened) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
// Toggle the flag status
|
||||
board[r][c].isFlagged = !board[r][c].isFlagged;
|
||||
});
|
||||
}
|
||||
|
||||
// --- GAME ACTION LOGIC ---
|
||||
Future<void> _checkWinCondition(
|
||||
MzansiProfileProvider profileProvider,
|
||||
MihMineSweeperProvider mihMineSweeperProvider,
|
||||
) async {
|
||||
// Game is won if all non-mine squares are opened.
|
||||
if (squaresLeft <= mihMineSweeperProvider.totalMines) {
|
||||
stopTimer();
|
||||
isGameWon = true;
|
||||
isGameOver = true;
|
||||
// win alert
|
||||
winAlert(mihMineSweeperProvider);
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return Mihloadingcircle(
|
||||
message: "Uploading your score",
|
||||
);
|
||||
});
|
||||
await MihMinesweeperServices().addPlayerScore(
|
||||
profileProvider,
|
||||
mihMineSweeperProvider,
|
||||
_formatTime().replaceAll("00:", ""),
|
||||
calculateGameScore(mihMineSweeperProvider),
|
||||
);
|
||||
context.pop();
|
||||
}
|
||||
}
|
||||
|
||||
Color? getDifficultyColor(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
String mode = mihMineSweeperProvider.difficulty;
|
||||
switch (mode) {
|
||||
case "Very Easy":
|
||||
return MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
);
|
||||
case "Easy":
|
||||
return MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark",
|
||||
);
|
||||
case "Intermediate":
|
||||
return MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
);
|
||||
case "Hard":
|
||||
return MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark",
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void loseAlert(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
showDialog(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: null,
|
||||
onWindowTapClose: null,
|
||||
backgroundColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
|
||||
windowBody: Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
Icon(
|
||||
FontAwesomeIcons.bomb,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
size: 125,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Better Luck Next Time",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Center(
|
||||
child: Text(
|
||||
"Your lost this game of MIH Minesweeper!!!",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Text(
|
||||
"Please feel free to start a New Game or check out the Leader Board to find out who's the best in Mzansi.",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
showStartGameWindow(mihMineSweeperProvider);
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"New Game",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"View Board",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
mihMineSweeperProvider.setToolIndex(1);
|
||||
},
|
||||
buttonColor: MihColors.getGoldColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Leader Board",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void winAlert(MihMineSweeperProvider mihMineSweeperProvider) {
|
||||
showDialog(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: null,
|
||||
onWindowTapClose: null,
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
windowBody: Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
Icon(
|
||||
Icons.celebration,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
size: 150,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Congratulations",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Text(
|
||||
"Your won this game of MIH Minesweeper!!!",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Time Taken: ${_formatTime().replaceAll("00:", "")}",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Score: ${calculateGameScore(mihMineSweeperProvider)}",
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
showStartGameWindow(mihMineSweeperProvider);
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"New Game",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"View Board",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
mihMineSweeperProvider.setLeaderboard(leaderboard: null);
|
||||
context.pop();
|
||||
mihMineSweeperProvider.setToolIndex(1);
|
||||
},
|
||||
buttonColor: MihColors.getGoldColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Leader Board",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// UBongani was here during the MIH Live
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody() {
|
||||
return Consumer2<MzansiProfileProvider, MihMineSweeperProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
MihMineSweeperProvider mihMineSweeperProvider, Widget? child) {
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
MihSingleChildScroll(
|
||||
child: board.isEmpty && squaresLeft < 0
|
||||
// Start Up Message before setting up game
|
||||
? Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.mineSweeper,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Welcom to Minesweeper, the first game of MIH.",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment:
|
||||
PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
Icons.menu,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
" to start a new game or learn how to play the minesweeper."),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
// Display Game Board when game started
|
||||
: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// Display game status
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10.0),
|
||||
child: Text(
|
||||
'Mines: ${mihMineSweeperProvider.totalMines}',
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10.0),
|
||||
child: Text(
|
||||
_formatTime().replaceAll("00:", ""),
|
||||
textAlign: TextAlign.right,
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
mihMineSweeperProvider.difficulty,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: getDifficultyColor(
|
||||
mihMineSweeperProvider),
|
||||
),
|
||||
),
|
||||
|
||||
// const SizedBox(
|
||||
// height: 30,
|
||||
// ),
|
||||
// The Board Grid
|
||||
SizedBox(
|
||||
width: mihMineSweeperProvider.columnCount *
|
||||
40.0, // Control size based on columns
|
||||
height: mihMineSweeperProvider.rowCount *
|
||||
40.0, // Control size based on rows
|
||||
child: GridView.builder(
|
||||
physics:
|
||||
const NeverScrollableScrollPhysics(), // Prevent scrolling
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount:
|
||||
mihMineSweeperProvider.columnCount,
|
||||
crossAxisSpacing: 0,
|
||||
mainAxisSpacing: 0,
|
||||
),
|
||||
itemCount: mihMineSweeperProvider.rowCount *
|
||||
mihMineSweeperProvider.columnCount,
|
||||
itemBuilder: (context, index) {
|
||||
int r = index ~/
|
||||
mihMineSweeperProvider
|
||||
.columnCount; // Integer division for row
|
||||
int c = index %
|
||||
mihMineSweeperProvider
|
||||
.columnCount; // Remainder for column
|
||||
|
||||
return MineTile(
|
||||
square: board[r][c],
|
||||
onTap: () => handleTap(profileProvider,
|
||||
mihMineSweeperProvider, r, c),
|
||||
onLongPress: () => handleLongPress(r, c),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 30),
|
||||
// const SizedBox(height: 100),
|
||||
],
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 10,
|
||||
bottom: 10,
|
||||
child: MihFloatingMenu(
|
||||
animatedIcon: AnimatedIcons.menu_close,
|
||||
children: [
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.rule_rounded,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
label: "Learn how to play",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onTap: () {
|
||||
mihMineSweeperProvider.setToolIndex(3);
|
||||
},
|
||||
),
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
label: "Start New Game",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onTap: () {
|
||||
showStartGameWindow(mihMineSweeperProvider);
|
||||
},
|
||||
),
|
||||
]),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
_timer != null ? MihBannerAd() : SizedBox(),
|
||||
SizedBox(height: 15),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,880 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MineSweeperQuickStartGuide extends StatefulWidget {
|
||||
const MineSweeperQuickStartGuide({super.key});
|
||||
|
||||
@override
|
||||
State<MineSweeperQuickStartGuide> createState() =>
|
||||
_MineSweeperQuickStartGuideState();
|
||||
}
|
||||
|
||||
class _MineSweeperQuickStartGuideState
|
||||
extends State<MineSweeperQuickStartGuide> {
|
||||
double titleSize = 22.0;
|
||||
double subtitleSize = 20.0;
|
||||
double pointsSize = 18.0;
|
||||
|
||||
Widget sectionOne() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: Column(
|
||||
children: [
|
||||
// Title
|
||||
Text(
|
||||
"1. Two Main Actions\n(Your Controls)",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: titleSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
//Part One
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: 'Quick Tap (or Click): This is the Dig action.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: subtitleSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: '• Goal:',
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' To uncover a square and see a number clue.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: '• Risk:',
|
||||
style: TextStyle(
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' If you click a mine, the game ends!',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
//Part Two
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text:
|
||||
'Tap and Hold (or Long Press): This is the Flag action (🚩).',
|
||||
style: TextStyle(
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: subtitleSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: '• Goal:',
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' To safely mark a square that you are',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' certain',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' is a mine.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: '• Risk:',
|
||||
style: TextStyle(
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
' Accidental placement of flags will cause confusion.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: '• Benefit:',
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
' You cannot accidentally click a square that is flagged.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget sectionTwo() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: Column(
|
||||
children: [
|
||||
// Title
|
||||
Text(
|
||||
"2. The Golden Rule\n(Reading the Numbers)",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: titleSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
//Part One
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text:
|
||||
'The number tells you exactly how many mines are touching that square (including sides and corners).',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: subtitleSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "• If you see a Blank Space (a '0'):",
|
||||
style: TextStyle(
|
||||
color: MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: " Zero (0) ",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
' mines are touching it. All surrounding squares are safe, and the game will open them for you automatically.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "• If you see a '1':",
|
||||
style: TextStyle(
|
||||
color: MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' Only ',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'one',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
' mine is touching this square. You must find and flag that single mine.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "• If you see a '3':",
|
||||
style: TextStyle(
|
||||
color: MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: " Three ",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
'mines are touching this square. You must find and flag all three.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget sectionThree() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: Column(
|
||||
children: [
|
||||
// Title
|
||||
Text(
|
||||
"3. The Winning Strategy\n(The Deduction Loop)",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: titleSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
//Part One
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text:
|
||||
'The game is won by uncovering every single safe square and correctly flagging all the mines. Use this two-step loop to clear the board:',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: subtitleSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: 'A. Find the Mines (Where to Flag 🚩)',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPurpleColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: subtitleSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: '• Goal:',
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
' Look for a number that only has one choice for a mine. e.g. If a \'1\' is touching only one hidden square, that hidden square',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' must ',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'be the mine.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: '• Action:',
|
||||
style: TextStyle(
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' Tap and Hold to place a',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' Flag ',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: 'on the square you are sure is a mine.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
//Part Two
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: 'B. Find the Safe Squares (Where to Dig)',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPurpleColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: subtitleSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: '• Goal:',
|
||||
style: TextStyle(
|
||||
color: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
' Look for a number that has been \'satisfied\' by your flags. e.g. You see a \'2\' and you have already placed two 🚩 flags touching it. The \'2\' is satisfied.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: '• Action:',
|
||||
style: TextStyle(
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode !=
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
' Quick Tap any of the remaining hidden squares touching that \'satisfied\' number. They',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: ' must be safe ',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
'because the mine requirement has already been met.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget sectionFour() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(15.0),
|
||||
child: Column(
|
||||
children: [
|
||||
// Title
|
||||
Text(
|
||||
"✨ Key Beginner Tips",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: titleSize,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "• Start on the Edges and Corners: ",
|
||||
style: TextStyle(
|
||||
color: MihColors.getBronze(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
'Numbers on the edge or corner of the board are easier to solve because they have fewer surrounding squares to check.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "• Don't Guess: ",
|
||||
style: TextStyle(
|
||||
color: MihColors.getBronze(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
'If you are down to two squares and either one could be the mine, look somewhere else on the board for a guaranteed, safe move.',
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.normal,
|
||||
fontSize: pointsSize,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
final double width = size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: Column(
|
||||
children: [
|
||||
const Text(
|
||||
'Simple Rules and Strategy',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Text(
|
||||
'Minesweeper is a puzzle game where you use numbers to figure out where the hidden bombs (mines) are located.',
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
// const Divider(height: 30),
|
||||
const SizedBox(height: 15),
|
||||
sectionOne(),
|
||||
const SizedBox(height: 15),
|
||||
sectionTwo(),
|
||||
const SizedBox(height: 15),
|
||||
sectionThree(),
|
||||
const SizedBox(height: 15),
|
||||
sectionFour(),
|
||||
const SizedBox(height: 15),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/builders/build_my_scoreboard_list.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_minesweeper_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MyScoreBoard extends StatefulWidget {
|
||||
const MyScoreBoard({super.key});
|
||||
|
||||
@override
|
||||
State<MyScoreBoard> createState() => _MihMineSweeperLeaderBoardState();
|
||||
}
|
||||
|
||||
class _MihMineSweeperLeaderBoardState extends State<MyScoreBoard> {
|
||||
TextEditingController filterController = TextEditingController();
|
||||
|
||||
Future<void> initialiseLeaderboard() async {
|
||||
MzansiProfileProvider profileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
MihMineSweeperProvider mineSweeperProvider =
|
||||
context.read<MihMineSweeperProvider>();
|
||||
filterController.text = mineSweeperProvider.difficulty;
|
||||
KenLogger.success("getting data");
|
||||
await MihMinesweeperServices()
|
||||
.getMyScoreboard(profileProvider, mineSweeperProvider);
|
||||
KenLogger.success("${mineSweeperProvider.myScoreboard}");
|
||||
}
|
||||
|
||||
void refreshLeaderBoard(
|
||||
MihMineSweeperProvider mineSweeperProvider, String difficulty) {
|
||||
mineSweeperProvider.setDifficulty(difficulty);
|
||||
mineSweeperProvider.setLeaderboard(leaderboard: null);
|
||||
mineSweeperProvider.setMyScoreboard(myScoreboard: null);
|
||||
initialiseLeaderboard();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await initialiseLeaderboard();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double width = MediaQuery.sizeOf(context).width;
|
||||
return Consumer<MihMineSweeperProvider>(
|
||||
builder: (BuildContext context,
|
||||
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
refreshLeaderBoard(mineSweeperProvider, filterController.text);
|
||||
},
|
||||
child: MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return Consumer2<MzansiProfileProvider, MihMineSweeperProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
|
||||
if (mineSweeperProvider.myScoreboard == null) {
|
||||
return Center(
|
||||
child: Mihloadingcircle(),
|
||||
);
|
||||
} else {
|
||||
return Column(
|
||||
children: [
|
||||
Center(
|
||||
child: MihCircleAvatar(
|
||||
imageFile: profileProvider.userProfilePicture,
|
||||
width: 150,
|
||||
editable: false,
|
||||
fileNameController: null,
|
||||
userSelectedfile: null,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onChange: (selectedImage) {},
|
||||
key: ValueKey(profileProvider.userProfilePicUrl),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
child: MihDropdownField(
|
||||
controller: filterController,
|
||||
hintText: "Scoreboards",
|
||||
dropdownOptions: const [
|
||||
"Very Easy",
|
||||
"Easy",
|
||||
"Intermediate",
|
||||
"Hard",
|
||||
],
|
||||
requiredText: true,
|
||||
editable: true,
|
||||
enableSearch: false,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
onSelected: (selection) {
|
||||
refreshLeaderBoard(mineSweeperProvider, selection!);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
mineSweeperProvider.myScoreboard!.isEmpty
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.mineSweeper,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"You have played and ${mineSweeperProvider.difficulty} yet.",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
FontAwesomeIcons.bomb,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(text: " and start a new game"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Expanded(child: BuildMyScoreBoardList()),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
111
mih_ui/lib/mih_packages/mzansi_ai/mzansi_ai.dart
Normal file
111
mih_ui/lib/mih_packages/mzansi_ai/mzansi_ai.dart
Normal file
@@ -0,0 +1,111 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_ai_provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tools/mih_ai_chat.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_data_helper_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MzansiAi extends StatefulWidget {
|
||||
const MzansiAi({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiAi> createState() => _MzansiAiState();
|
||||
}
|
||||
|
||||
class _MzansiAiState extends State<MzansiAi> {
|
||||
bool _isLoadingInitialData = true;
|
||||
late final MihAiChat _aiChat;
|
||||
|
||||
Future<void> _loadInitialData() async {
|
||||
setState(() {
|
||||
_isLoadingInitialData = true;
|
||||
});
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
if (mzansiProfileProvider.user == null) {
|
||||
await MihDataHelperServices().loadUserDataOnly(
|
||||
mzansiProfileProvider,
|
||||
);
|
||||
}
|
||||
setState(() {
|
||||
_isLoadingInitialData = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_aiChat = MihAiChat();
|
||||
_loadInitialData();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiAiProvider>(
|
||||
builder: (BuildContext context, MzansiAiProvider value, Widget? child) {
|
||||
if (_isLoadingInitialData) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Mihloadingcircle(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: context.watch<MzansiAiProvider>().toolIndex,
|
||||
onIndexChange: (newValue) {
|
||||
context.read<MzansiAiProvider>().setToolIndex(newValue);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.read<MzansiAiProvider>().setStartUpQuestion(null);
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.chat)] = () {
|
||||
context.read<MzansiAiProvider>().setToolIndex(0);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MzansiAiProvider>().toolIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_aiChat,
|
||||
];
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Ask Mzansi",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import 'package:go_router/go_router.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_package_components/mih_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MzansiAiTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
|
||||
const MzansiAiTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiAiTile> createState() => _MzansiAiTileState();
|
||||
}
|
||||
|
||||
class _MzansiAiTileState extends State<MzansiAiTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageTile(
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mzansiAi',
|
||||
);
|
||||
// Navigator.of(context).pushNamed(
|
||||
// '/mzansi-ai',
|
||||
// arguments: MzansiAiArguments(
|
||||
// widget.signedInUser,
|
||||
// "",
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
appName: "Mzansi AI",
|
||||
appIcon: Icon(
|
||||
MihIcons.mzansiAi,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: widget.packageSize,
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
388
mih_ui/lib/mih_packages/mzansi_ai/package_tools/mih_ai_chat.dart
Normal file
388
mih_ui/lib/mih_packages/mzansi_ai/package_tools/mih_ai_chat.dart
Normal file
@@ -0,0 +1,388 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_ai_toolkit/flutter_ai_toolkit.dart';
|
||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||
import 'package:flutter_tts/flutter_tts.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_floating_menu.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_ai_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihAiChat extends StatefulWidget {
|
||||
const MihAiChat({super.key});
|
||||
|
||||
@override
|
||||
State<MihAiChat> createState() => _MihAiChatState();
|
||||
}
|
||||
|
||||
class _MihAiChatState extends State<MihAiChat> with WidgetsBindingObserver {
|
||||
final FlutterTts _flutterTts = FlutterTts();
|
||||
bool _isKeyboardVisible = false;
|
||||
|
||||
Widget noMessagescDisplay() {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.mzansiAi,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Mzansi AI is here to help",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text:
|
||||
"Send us a message and we'll try our best to assist you"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
Icons.menu,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(text: " to start a new chat or read last message"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void resetChat(MzansiAiProvider aiProvider) {
|
||||
aiProvider.ollamaProvider.resetChat();
|
||||
}
|
||||
|
||||
void speakLastMessage(MzansiAiProvider aiProvider) {
|
||||
final history = aiProvider.ollamaProvider.history;
|
||||
if (history.isNotEmpty) {
|
||||
final historyList = history.toList();
|
||||
for (int i = historyList.length - 1; i >= 0; i--) {
|
||||
if (historyList[i].origin == MessageOrigin.llm &&
|
||||
historyList[i].text != null &&
|
||||
historyList[i].text!.isNotEmpty) {
|
||||
_flutterTts.speak(historyList[i].text!);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void saveHistory(
|
||||
MzansiProfileProvider profileProvider, MzansiAiProvider aiProvider) {
|
||||
final history = aiProvider.ollamaProvider.history.toList();
|
||||
DateTime now = DateTime.now();
|
||||
DateFormat formatter = DateFormat('yyyy-MM-ddTHH:mm:ss');
|
||||
String formattedDateTimeNow = formatter.format(now);
|
||||
|
||||
// 1. Build the list of message Maps
|
||||
List<Map<String, dynamic>> messages = [];
|
||||
for (int i = 0; i < history.length; i++) {
|
||||
final map = history[i].toJson();
|
||||
map["order"] = i; // Add the order field
|
||||
messages.add(map);
|
||||
}
|
||||
|
||||
// 2. Build the main history Map (the root JSON object)
|
||||
final historyMap = <String, dynamic>{
|
||||
"conversation_id": "1234-asdf-5678-qwert",
|
||||
"app_id": profileProvider.user!.app_id,
|
||||
"modified_date": formattedDateTimeNow,
|
||||
"messages": messages, // The list of messages is included here
|
||||
};
|
||||
|
||||
// 3. Use JsonEncoder to convert the entire Map to a formatted JSON string
|
||||
const encoder = JsonEncoder.withIndent(' ');
|
||||
String jsonHistory = encoder.convert(historyMap);
|
||||
|
||||
// The output string will now be a correctly formatted and escaped JSON object.
|
||||
debugPrint("History: $jsonHistory");
|
||||
}
|
||||
|
||||
// void saveHistory(
|
||||
// MzansiProfileProvider profileProvider, MzansiAiProvider aiProvider) {
|
||||
// final history = aiProvider.ollamaProvider.history.toList();
|
||||
// DateTime now = DateTime.now();
|
||||
// DateFormat formatter = DateFormat('yyyy-MM-ddTHH:mm:ss');
|
||||
// String formattedDateTimeNow = formatter.format(now);
|
||||
// String jsonHistory = '{"conversation_id":"1234-asdf-5678-qwert",\n';
|
||||
// jsonHistory += '"app_id":"${profileProvider.user!.app_id}",\n';
|
||||
// jsonHistory += '"modified_date":"$formattedDateTimeNow",\n';
|
||||
// jsonHistory += '"messages":[\n';
|
||||
// KenLogger.success("History Length: ${history.length}");
|
||||
// for (int i = 0; i != history.length; i++) {
|
||||
// final map = history[i].toJson();
|
||||
// map["order"] = i;
|
||||
// final json = JsonEncoder.withIndent(' ').convert(map);
|
||||
// jsonHistory += json;
|
||||
// if (i != history.length - 1) {
|
||||
// KenLogger.success("i: $i");
|
||||
// jsonHistory += ",";
|
||||
// }
|
||||
// jsonHistory += "\n";
|
||||
// }
|
||||
// jsonHistory += ']}';
|
||||
// debugPrint("History: $jsonHistory");
|
||||
// }
|
||||
|
||||
void stopTTS(MzansiAiProvider aiProvider) {
|
||||
_flutterTts.stop();
|
||||
aiProvider.setTTSstate(false);
|
||||
}
|
||||
|
||||
Future<void> initTts(MzansiAiProvider aiProvider) async {
|
||||
try {
|
||||
await _flutterTts.setSpeechRate(!kIsWeb ? 0.55 : 1);
|
||||
// await _flutterTts.setLanguage("en-US");
|
||||
|
||||
// Safer voice selection with error handling
|
||||
_flutterTts.getVoices.then((data) {
|
||||
try {
|
||||
final voices = List<Map>.from(data);
|
||||
final englishVoices = voices.where((voice) {
|
||||
final name = voice["name"]?.toString().toLowerCase() ?? '';
|
||||
final locale = voice["locale"]?.toString().toLowerCase() ?? '';
|
||||
return name.contains("en-us") || locale.contains("en_us");
|
||||
}).toList();
|
||||
|
||||
if (englishVoices.isNotEmpty) {
|
||||
// Use the first available English voice
|
||||
_flutterTts.setVoice({"name": englishVoices.first["name"]});
|
||||
}
|
||||
// If no voices found, use default
|
||||
} catch (e) {
|
||||
KenLogger.error("Error setting TTS voice: $e");
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
KenLogger.error("Error initializing TTS: $e");
|
||||
}
|
||||
|
||||
_flutterTts.setStartHandler(() {
|
||||
if (mounted) {
|
||||
aiProvider.setTTSstate(true);
|
||||
}
|
||||
});
|
||||
|
||||
_flutterTts.setCompletionHandler(() {
|
||||
if (mounted) {
|
||||
aiProvider.setTTSstate(false);
|
||||
}
|
||||
});
|
||||
|
||||
_flutterTts.setErrorHandler((message) {
|
||||
if (mounted) {
|
||||
aiProvider.setTTSstate(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void initStartQuestion() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
final mzansiAiProvider = context.read<MzansiAiProvider>();
|
||||
final startQuestion = mzansiAiProvider.startUpQuestion;
|
||||
if (startQuestion != null && startQuestion.isNotEmpty) {
|
||||
final stream =
|
||||
mzansiAiProvider.ollamaProvider.sendMessageStream(startQuestion);
|
||||
stream.listen((chunk) {});
|
||||
mzansiAiProvider.clearStartUpQuestion();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
MzansiAiProvider aiProvider = context.read<MzansiAiProvider>();
|
||||
initTts(aiProvider);
|
||||
initStartQuestion();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_flutterTts.stop();
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeMetrics() {
|
||||
final bottomInset = WidgetsBinding
|
||||
.instance.platformDispatcher.views.first.viewInsets.bottom;
|
||||
setState(() {
|
||||
_isKeyboardVisible = bottomInset > 0;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer2<MzansiProfileProvider, MzansiAiProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
MzansiAiProvider aiProvider, Widget? child) {
|
||||
bool hasHistory = aiProvider.ollamaProvider.history.isNotEmpty;
|
||||
String? lastMessage;
|
||||
if (hasHistory) {
|
||||
final histroyList = aiProvider.ollamaProvider.history.toList();
|
||||
lastMessage = histroyList[histroyList.length - 1].text;
|
||||
}
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
LlmChatView(
|
||||
provider: aiProvider.ollamaProvider,
|
||||
messageSender: aiProvider.ollamaProvider.sendMessageStream,
|
||||
speechToText: aiProvider.ollamaProvider.speechToText,
|
||||
// welcomeMessage:
|
||||
// "Mzansi AI is here to help. Send us a messahe and we'll try our best to assist you.",
|
||||
autofocus: false,
|
||||
enableAttachments: true,
|
||||
enableVoiceNotes: false,
|
||||
style: aiProvider.getChatStyle(context),
|
||||
suggestions: [
|
||||
"What is MIH all about?",
|
||||
"What are the features of MIH?"
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
top: 10,
|
||||
left: 10,
|
||||
child: MihButton(
|
||||
width: 200,
|
||||
height: 30,
|
||||
onPressed: () {
|
||||
saveHistory(profileProvider, aiProvider);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: Text(
|
||||
"View History as json",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hasHistory && lastMessage != null)
|
||||
Positioned(
|
||||
bottom: 80,
|
||||
left: 10,
|
||||
child: MihButton(
|
||||
width: 35,
|
||||
height: 35,
|
||||
onPressed: () {
|
||||
if (!aiProvider.ttsOn) {
|
||||
speakLastMessage(aiProvider);
|
||||
} else {
|
||||
stopTTS(aiProvider);
|
||||
}
|
||||
},
|
||||
buttonColor: !aiProvider.ttsOn
|
||||
? MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
|
||||
: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
child: Icon(
|
||||
!aiProvider.ttsOn ? Icons.volume_up : Icons.volume_off,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 10,
|
||||
bottom: 80,
|
||||
child: MihFloatingMenu(
|
||||
animatedIcon: AnimatedIcons.menu_close,
|
||||
children: [
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.refresh,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
label: "New Chat",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
resetChat(aiProvider);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!hasHistory && !_isKeyboardVisible) noMessagescDisplay(),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
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/business.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_business_profile_preview.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class BuildBusinessSearchResultsList extends StatefulWidget {
|
||||
final List<Business> businessList;
|
||||
const BuildBusinessSearchResultsList({
|
||||
super.key,
|
||||
required this.businessList,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildBusinessSearchResultsList> createState() =>
|
||||
_BuildBusinessSearchResultsListState();
|
||||
}
|
||||
|
||||
class _BuildBusinessSearchResultsListState
|
||||
extends State<BuildBusinessSearchResultsList> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiDirectoryProvider>(
|
||||
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
|
||||
Widget? child) {
|
||||
return ListView.separated(
|
||||
// shrinkWrap: true,
|
||||
// physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: widget.businessList.length,
|
||||
separatorBuilder: (BuildContext context, index) {
|
||||
return Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
return Material(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
directoryProvider.setSelectedBusiness(
|
||||
business: widget.businessList[index],
|
||||
);
|
||||
context.pushNamed(
|
||||
'businessProfileView',
|
||||
);
|
||||
},
|
||||
splashColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
|
||||
.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
child: Padding(
|
||||
padding: EdgeInsetsGeometry.symmetric(
|
||||
// vertical: 5,
|
||||
horizontal: 25,
|
||||
),
|
||||
child: FutureBuilder(
|
||||
future: directoryProvider.busSearchImagesUrl![
|
||||
widget.businessList[index].business_id],
|
||||
builder: (context, asyncSnapshot) {
|
||||
ImageProvider<Object>? imageFile;
|
||||
bool loading = true;
|
||||
if (asyncSnapshot.connectionState ==
|
||||
ConnectionState.done) {
|
||||
loading = false;
|
||||
if (asyncSnapshot.hasData) {
|
||||
imageFile = asyncSnapshot.requireData != ""
|
||||
? CachedNetworkImageProvider(
|
||||
asyncSnapshot.requireData)
|
||||
: null;
|
||||
} else {
|
||||
imageFile = null;
|
||||
}
|
||||
} else {
|
||||
imageFile = null;
|
||||
}
|
||||
return MihBusinessProfilePreview(
|
||||
business: widget.businessList[index],
|
||||
imageFile: imageFile,
|
||||
loading: loading,
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
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/business.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_business_profile_preview.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class BuildFavouriteBusinessesList extends StatefulWidget {
|
||||
final List<Business?> favouriteBusinesses;
|
||||
const BuildFavouriteBusinessesList({
|
||||
super.key,
|
||||
required this.favouriteBusinesses,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildFavouriteBusinessesList> createState() =>
|
||||
_BuildFavouriteBusinessesListState();
|
||||
}
|
||||
|
||||
class _BuildFavouriteBusinessesListState
|
||||
extends State<BuildFavouriteBusinessesList> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiDirectoryProvider>(
|
||||
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
|
||||
Widget? child) {
|
||||
return ListView.separated(
|
||||
itemCount: widget.favouriteBusinesses.length,
|
||||
separatorBuilder: (BuildContext context, index) {
|
||||
return Divider(
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
);
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
if (widget.favouriteBusinesses[index] == null) {
|
||||
return const SizedBox(); // Or a placeholder if a business couldn't be loaded
|
||||
}
|
||||
return Material(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
directoryProvider.setSelectedBusiness(
|
||||
business: widget.favouriteBusinesses[index]!,
|
||||
);
|
||||
context.pushNamed(
|
||||
'businessProfileView',
|
||||
);
|
||||
},
|
||||
splashColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
|
||||
.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 25,
|
||||
),
|
||||
child: FutureBuilder(
|
||||
future: directoryProvider.favBusImagesUrl![
|
||||
widget.favouriteBusinesses[index]!.business_id],
|
||||
builder: (context, asyncSnapshot) {
|
||||
ImageProvider<Object>? imageFile;
|
||||
bool loading = true;
|
||||
if (asyncSnapshot.connectionState ==
|
||||
ConnectionState.done) {
|
||||
loading = false;
|
||||
if (asyncSnapshot.hasData) {
|
||||
imageFile = asyncSnapshot.requireData != ""
|
||||
? CachedNetworkImageProvider(
|
||||
asyncSnapshot.requireData)
|
||||
: null;
|
||||
} else {
|
||||
imageFile = null;
|
||||
}
|
||||
} else {
|
||||
imageFile = null;
|
||||
}
|
||||
return MihBusinessProfilePreview(
|
||||
business: widget.favouriteBusinesses[index]!,
|
||||
imageFile: imageFile,
|
||||
loading: loading,
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
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/app_user.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_personal_profile_preview.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class BuildUserSearchResultsList extends StatefulWidget {
|
||||
final List<AppUser> userList;
|
||||
const BuildUserSearchResultsList({
|
||||
super.key,
|
||||
required this.userList,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildUserSearchResultsList> createState() =>
|
||||
_BuildUserSearchResultsListState();
|
||||
}
|
||||
|
||||
class _BuildUserSearchResultsListState
|
||||
extends State<BuildUserSearchResultsList> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiDirectoryProvider>(
|
||||
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
|
||||
Widget? child) {
|
||||
return ListView.separated(
|
||||
// shrinkWrap: true,
|
||||
// physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: widget.userList.length,
|
||||
separatorBuilder: (BuildContext context, index) {
|
||||
return Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
},
|
||||
itemBuilder: (context, index) {
|
||||
return Material(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
directoryProvider.setSelectedUser(
|
||||
user: widget.userList[index]);
|
||||
context.pushNamed(
|
||||
'mzansiProfileView',
|
||||
);
|
||||
},
|
||||
splashColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
|
||||
.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
child: Padding(
|
||||
padding: EdgeInsetsGeometry.symmetric(
|
||||
// vertical: 5,
|
||||
horizontal: 25,
|
||||
),
|
||||
child: FutureBuilder(
|
||||
future: directoryProvider
|
||||
.userSearchImagesUrl![widget.userList[index].app_id],
|
||||
builder: (context, asyncSnapshot) {
|
||||
ImageProvider<Object>? imageFile;
|
||||
bool loading = true;
|
||||
if (asyncSnapshot.connectionState ==
|
||||
ConnectionState.done) {
|
||||
loading = false;
|
||||
if (asyncSnapshot.hasData) {
|
||||
imageFile = asyncSnapshot.requireData != ""
|
||||
? CachedNetworkImageProvider(
|
||||
asyncSnapshot.requireData)
|
||||
: null;
|
||||
} else {
|
||||
imageFile = null;
|
||||
}
|
||||
} else {
|
||||
imageFile = null;
|
||||
}
|
||||
return MihPersonalProfilePreview(
|
||||
user: widget.userList[index],
|
||||
imageFile: imageFile,
|
||||
loading: loading,
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
136
mih_ui/lib/mih_packages/mzansi_directory/mzansi_directory.dart
Normal file
136
mih_ui/lib/mih_packages/mzansi_directory/mzansi_directory.dart
Normal file
@@ -0,0 +1,136 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tools/mih_favourite_businesses.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tools/mih_search_mzansi.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_data_helper_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MzansiDirectory extends StatefulWidget {
|
||||
const MzansiDirectory({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiDirectory> createState() => _MzansiDirectoryState();
|
||||
}
|
||||
|
||||
class _MzansiDirectoryState extends State<MzansiDirectory> {
|
||||
bool _isLoadingInitialData = true;
|
||||
late Future<Position?> futurePosition =
|
||||
MIHLocationAPI().getGPSPosition(context);
|
||||
late final MihSearchMzansi _searchTool;
|
||||
late final MihFavouriteBusinesses _favouritesTool;
|
||||
|
||||
Future<void> _loadInitialData() async {
|
||||
setState(() {
|
||||
_isLoadingInitialData = true;
|
||||
});
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
if (mzansiProfileProvider.user == null) {
|
||||
await MihDataHelperServices().loadUserDataOnly(
|
||||
mzansiProfileProvider,
|
||||
);
|
||||
}
|
||||
setState(() {
|
||||
_isLoadingInitialData = false;
|
||||
});
|
||||
initialiseGPSLocation();
|
||||
}
|
||||
|
||||
Future<void> initialiseGPSLocation() async {
|
||||
MzansiDirectoryProvider directoryProvider =
|
||||
context.read<MzansiDirectoryProvider>();
|
||||
Position? userPos = await MIHLocationAPI().getGPSPosition(context);
|
||||
directoryProvider.setUserPosition(userPos);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_searchTool = const MihSearchMzansi();
|
||||
_favouritesTool = const MihFavouriteBusinesses();
|
||||
_loadInitialData();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiDirectoryProvider>(
|
||||
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
|
||||
Widget? child) {
|
||||
if (_isLoadingInitialData) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Mihloadingcircle(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: directoryProvider.toolIndex,
|
||||
onIndexChange: (newValue) {
|
||||
directoryProvider.setToolIndex(newValue);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_searchTool,
|
||||
_favouritesTool,
|
||||
];
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
MzansiDirectoryProvider directoryProvider =
|
||||
context.read<MzansiDirectoryProvider>();
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
directoryProvider.setToolIndex(0);
|
||||
directoryProvider.setPersonalSearch(true);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.search)] = () {
|
||||
context.read<MzansiDirectoryProvider>().setToolIndex(0);
|
||||
};
|
||||
temp[const Icon(Icons.business_center)] = () {
|
||||
context.read<MzansiDirectoryProvider>().setToolIndex(1);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MzansiDirectoryProvider>().toolIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Mzansi Search",
|
||||
"Favourite Businesses",
|
||||
// "Contacts",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
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_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tile.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MzansiDirectoryTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
const MzansiDirectoryTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiDirectoryTile> createState() => _MzansiDirectoryTileState();
|
||||
}
|
||||
|
||||
class _MzansiDirectoryTileState extends State<MzansiDirectoryTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageTile(
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
"mzansiDirectory",
|
||||
);
|
||||
// Navigator.of(context).pushNamed(
|
||||
// '/mzansi-directory',
|
||||
// arguments: MzansiDirectoryArguments(
|
||||
// personalSearch: true,
|
||||
// startSearchText: null,
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
appName: "Mzansi Directory",
|
||||
appIcon: Icon(
|
||||
MihIcons.mzansiDirectory,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: widget.packageSize,
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_search_bar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MihContacts extends StatefulWidget {
|
||||
const MihContacts({super.key});
|
||||
|
||||
@override
|
||||
State<MihContacts> createState() => _MihContactsState();
|
||||
}
|
||||
|
||||
class _MihContactsState extends State<MihContacts> {
|
||||
final TextEditingController contactSearchController = TextEditingController();
|
||||
final FocusNode searchFocusNode = FocusNode();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
final double width = size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return MihSingleChildScroll(
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: MihSearchBar(
|
||||
controller: contactSearchController,
|
||||
hintText: "Search Contacts",
|
||||
prefixIcon: Icons.search,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
hintColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onPrefixIconTap: () {},
|
||||
searchFocusNode: searchFocusNode,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/business.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_search_bar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.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_directory/builders/build_favourite_businesses_list.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.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';
|
||||
|
||||
class MihFavouriteBusinesses extends StatefulWidget {
|
||||
const MihFavouriteBusinesses({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihFavouriteBusinesses> createState() => _MihFavouriteBusinessesState();
|
||||
}
|
||||
|
||||
class _MihFavouriteBusinessesState extends State<MihFavouriteBusinesses> {
|
||||
final TextEditingController businessSearchController =
|
||||
TextEditingController();
|
||||
final FocusNode searchFocusNode = FocusNode();
|
||||
final ValueNotifier<List<Business?>> searchBookmarkedBusinesses =
|
||||
ValueNotifier([]);
|
||||
Timer? _debounce;
|
||||
|
||||
Future<void> getFavouriteBusinesses(
|
||||
MzansiDirectoryProvider directoryProvider) async {
|
||||
MzansiProfileProvider profileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
if (directoryProvider.bookmarkedBusinesses.isEmpty) {
|
||||
await MihMzansiDirectoryServices().getAllUserBookmarkedBusiness(
|
||||
profileProvider.user!.app_id,
|
||||
directoryProvider,
|
||||
);
|
||||
List<Business> favBus = [];
|
||||
Map<String, Future<String>> favBusImages = {};
|
||||
Future<String> businessLogoUrl;
|
||||
for (var bus in directoryProvider.bookmarkedBusinesses) {
|
||||
await MihBusinessDetailsServices()
|
||||
.getBusinessDetailsByBusinessId(bus.business_id)
|
||||
.then((business) async {
|
||||
favBus.add(business!);
|
||||
businessLogoUrl = MihFileApi.getMinioFileUrl(business.logo_path);
|
||||
favBusImages[business.business_id] = businessLogoUrl;
|
||||
});
|
||||
}
|
||||
directoryProvider.setFavouriteBusinesses(
|
||||
businesses: favBus,
|
||||
businessesImagesUrl: favBusImages,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _filterAndSetBusinesses(MzansiDirectoryProvider directoryProvider) {
|
||||
List<Business?> businessesToDisplay = [];
|
||||
String query = businessSearchController.text.toLowerCase();
|
||||
if (directoryProvider.favouriteBusinessesList != null) {
|
||||
for (var bus in directoryProvider.favouriteBusinessesList!) {
|
||||
if (bus.Name.toLowerCase().contains(query)) {
|
||||
businessesToDisplay.add(bus);
|
||||
}
|
||||
}
|
||||
}
|
||||
searchBookmarkedBusinesses.value = businessesToDisplay;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
businessSearchController.dispose();
|
||||
searchFocusNode.dispose();
|
||||
searchBookmarkedBusinesses.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
MzansiDirectoryProvider directoryProvider =
|
||||
context.read<MzansiDirectoryProvider>();
|
||||
// getAndMapAllBusinessDetailsForBookmarkedBusinesses(
|
||||
// mzansiProfileProvider,
|
||||
// directoryProvider,
|
||||
// );
|
||||
getFavouriteBusinesses(directoryProvider);
|
||||
_filterAndSetBusinesses(directoryProvider);
|
||||
businessSearchController.addListener(() {
|
||||
if (_debounce?.isActive ?? false) {
|
||||
_debounce!.cancel();
|
||||
}
|
||||
_debounce = Timer(const Duration(milliseconds: 200), () {
|
||||
_filterAndSetBusinesses(directoryProvider);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
final double width = size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return Consumer<MzansiDirectoryProvider>(
|
||||
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
|
||||
Widget? child) {
|
||||
if (directoryProvider.favouriteBusinessesList == null) {
|
||||
return Center(
|
||||
child: Mihloadingcircle(),
|
||||
);
|
||||
}
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: MihSearchBar(
|
||||
controller: businessSearchController,
|
||||
hintText: "Search Businesses",
|
||||
prefixIcon: Icons.search,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
hintColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onPrefixIconTap: () {},
|
||||
searchFocusNode: searchFocusNode,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: ValueListenableBuilder<List<Business?>>(
|
||||
valueListenable: searchBookmarkedBusinesses,
|
||||
builder: (context, filteredBusinesses, child) {
|
||||
if (filteredBusinesses.isEmpty &&
|
||||
businessSearchController.text.isNotEmpty) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.iDontKnow,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Let's try refining your search",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else if (filteredBusinesses.isEmpty &&
|
||||
businessSearchController.text.isEmpty) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.businessProfile,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"No favourite businesses added to your mzansi directory",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Use the mzansi search"),
|
||||
TextSpan(
|
||||
text:
|
||||
" to find your favourite businesses of mzansi"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
// KenLogger.success(filteredBusinesses);
|
||||
return BuildFavouriteBusinessesList(
|
||||
favouriteBusinesses: filteredBusinesses,
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,573 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/app_user.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/business.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_search_bar.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_directory_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_business_search_resultsList.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_user_search_results_list.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_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_user_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihSearchMzansi extends StatefulWidget {
|
||||
const MihSearchMzansi({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihSearchMzansi> createState() => _MihSearchMzansiState();
|
||||
}
|
||||
|
||||
class _MihSearchMzansiState extends State<MihSearchMzansi> {
|
||||
final TextEditingController mzansiSearchController = TextEditingController();
|
||||
final TextEditingController businessTypeController = TextEditingController();
|
||||
final FocusNode searchFocusNode = FocusNode();
|
||||
// late bool userSearch;
|
||||
// Future<List<AppUser>?> futureUserSearchResults = Future.value();
|
||||
List<AppUser> userSearchResults = [];
|
||||
List<Business> businessSearchResults = [];
|
||||
late Future<List<String>> availableBusinessTypes;
|
||||
bool filterOn = false;
|
||||
bool loadingSearchResults = false;
|
||||
|
||||
Future<void> swapPressed(MzansiProfileProvider profileProvider,
|
||||
MzansiDirectoryProvider directoryProvider) async {
|
||||
directoryProvider.setPersonalSearch(!directoryProvider.personalSearch);
|
||||
setState(() {
|
||||
if (filterOn) {
|
||||
filterOn = !filterOn;
|
||||
}
|
||||
});
|
||||
if (businessTypeController.text.isNotEmpty) {
|
||||
setState(() {
|
||||
businessTypeController.clear();
|
||||
});
|
||||
}
|
||||
await searchPressed(profileProvider, directoryProvider);
|
||||
}
|
||||
|
||||
void clearAll(MzansiDirectoryProvider directoryProvider) {
|
||||
directoryProvider
|
||||
.setSearchedBusinesses(searchedBusinesses: [], businessesImagesUrl: {});
|
||||
directoryProvider.setSearchedUsers(searchedUsers: [], userImagesUrl: {});
|
||||
directoryProvider.setSearchTerm(searchTerm: "");
|
||||
setState(() {
|
||||
mzansiSearchController.clear();
|
||||
businessTypeController.clear();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> searchPressed(MzansiProfileProvider profileProvider,
|
||||
MzansiDirectoryProvider directoryProvider) async {
|
||||
setState(() {
|
||||
loadingSearchResults = true;
|
||||
});
|
||||
directoryProvider.setSearchTerm(searchTerm: mzansiSearchController.text);
|
||||
directoryProvider.setBusinessTypeFilter(
|
||||
businessTypeFilter: businessTypeController.text);
|
||||
if (directoryProvider.personalSearch &&
|
||||
directoryProvider.searchTerm.isNotEmpty) {
|
||||
final userResults = await MihUserServices()
|
||||
.searchUsers(profileProvider, directoryProvider.searchTerm, context);
|
||||
Map<String, Future<String>> userImages = {};
|
||||
Future<String> usernProPicUrl;
|
||||
for (var user in userResults) {
|
||||
KenLogger.success("Business Logo Path: ${user.pro_pic_path}");
|
||||
usernProPicUrl = MihFileApi.getMinioFileUrl(user.pro_pic_path);
|
||||
KenLogger.success("Business Logo Path: ${user.pro_pic_path}");
|
||||
userImages[user.app_id] = usernProPicUrl;
|
||||
// != ""
|
||||
// ? CachedNetworkImageProvider(usernProPicUrl)
|
||||
// : null;
|
||||
}
|
||||
|
||||
directoryProvider.setSearchedUsers(
|
||||
searchedUsers: userResults,
|
||||
userImagesUrl: userImages,
|
||||
);
|
||||
} else {
|
||||
List<Business>? businessSearchResults = [];
|
||||
if (directoryProvider.businessTypeFilter.isNotEmpty) {
|
||||
businessSearchResults = await MihBusinessDetailsServices()
|
||||
.searchBusinesses(directoryProvider.searchTerm,
|
||||
directoryProvider.businessTypeFilter, context);
|
||||
} else if (directoryProvider.searchTerm.isNotEmpty) {
|
||||
businessSearchResults = await MihBusinessDetailsServices()
|
||||
.searchBusinesses(directoryProvider.searchTerm,
|
||||
directoryProvider.businessTypeFilter, context);
|
||||
}
|
||||
Map<String, Future<String>> busImagesUrl = {};
|
||||
Future<String> businessLogoUrl;
|
||||
for (var bus in businessSearchResults) {
|
||||
KenLogger.success("Business Logo Path: ${bus.logo_path}");
|
||||
businessLogoUrl = MihFileApi.getMinioFileUrl(bus.logo_path);
|
||||
KenLogger.success("Business Logo Path: ${bus.logo_path}");
|
||||
busImagesUrl[bus.business_id] = businessLogoUrl;
|
||||
// != ""
|
||||
// ? CachedNetworkImageProvider(businessLogoUrl)
|
||||
// : null;
|
||||
}
|
||||
directoryProvider.setSearchedBusinesses(
|
||||
searchedBusinesses: businessSearchResults,
|
||||
businessesImagesUrl: busImagesUrl,
|
||||
);
|
||||
}
|
||||
setState(() {
|
||||
loadingSearchResults = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
businessTypeController.dispose();
|
||||
mzansiSearchController.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
MzansiDirectoryProvider directoryProvider =
|
||||
context.read<MzansiDirectoryProvider>();
|
||||
availableBusinessTypes =
|
||||
MihBusinessDetailsServices().fetchAllBusinessTypes();
|
||||
mzansiSearchController.text = directoryProvider.searchTerm;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
final double width = size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return Consumer2<MzansiProfileProvider, MzansiDirectoryProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
MzansiDirectoryProvider directoryProvider, Widget? child) {
|
||||
return Column(
|
||||
children: [
|
||||
Text(
|
||||
directoryProvider.personalSearch
|
||||
? "People Search"
|
||||
: "Businesses Search",
|
||||
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: MihSearchBar(
|
||||
controller: mzansiSearchController,
|
||||
hintText: "Search Mzansi",
|
||||
prefixIcon: Icons.search,
|
||||
prefixAltIcon: directoryProvider.personalSearch
|
||||
? Icons.person
|
||||
: Icons.business,
|
||||
suffixTools: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
swapPressed(profileProvider, directoryProvider);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.swap_horiz_rounded,
|
||||
size: 35,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
hintColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onPrefixIconTap: () {
|
||||
searchPressed(profileProvider, directoryProvider);
|
||||
},
|
||||
onClearIconTap: () {
|
||||
clearAll(directoryProvider);
|
||||
},
|
||||
searchFocusNode: searchFocusNode,
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: !directoryProvider.personalSearch,
|
||||
child: const SizedBox(width: 10),
|
||||
),
|
||||
Visibility(
|
||||
visible: !directoryProvider.personalSearch,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
if (filterOn) {
|
||||
clearAll(directoryProvider);
|
||||
}
|
||||
setState(() {
|
||||
filterOn = !filterOn;
|
||||
});
|
||||
},
|
||||
icon: Icon(
|
||||
!filterOn
|
||||
? Icons.filter_list_rounded
|
||||
: Icons.filter_list_off_rounded,
|
||||
size: 35,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
FutureBuilder(
|
||||
future: availableBusinessTypes,
|
||||
builder: (context, asyncSnapshot) {
|
||||
List<String> options = [];
|
||||
if (asyncSnapshot.connectionState == ConnectionState.done) {
|
||||
options.addAll(asyncSnapshot.data!);
|
||||
}
|
||||
return Visibility(
|
||||
visible: filterOn,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Expanded(
|
||||
child: MihDropdownField(
|
||||
controller: businessTypeController,
|
||||
hintText: "Business Type",
|
||||
dropdownOptions: options,
|
||||
requiredText: true,
|
||||
editable: true,
|
||||
enableSearch: true,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
if (businessTypeController.text.isNotEmpty) {
|
||||
searchPressed(
|
||||
profileProvider, directoryProvider);
|
||||
} else {
|
||||
MihAlertServices().errorBasicAlert(
|
||||
"Business Type Not Selected",
|
||||
"Please ensure you have selected a Business Type before seareching for Businesses of Mzansi",
|
||||
context,
|
||||
);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
elevation: 10,
|
||||
child: Text(
|
||||
"Search",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
const SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: directoryProvider.personalSearch
|
||||
? displayPersonalSearchResults(directoryProvider)
|
||||
: displayBusinessSearchResults(directoryProvider),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget displayBusinessSearchResults(
|
||||
MzansiDirectoryProvider directoryProvider) {
|
||||
if (loadingSearchResults) {
|
||||
return Center(
|
||||
child: const Mihloadingcircle(),
|
||||
);
|
||||
} else if (directoryProvider.searchedBusinesses.isNotEmpty) {
|
||||
// return Text("Pulled Data successfully");
|
||||
directoryProvider.searchedBusinesses
|
||||
.sort((a, b) => a.Name.compareTo(b.Name));
|
||||
return BuildBusinessSearchResultsList(
|
||||
businessList: directoryProvider.searchedBusinesses,
|
||||
);
|
||||
} else if (directoryProvider.searchedBusinesses.isEmpty &&
|
||||
directoryProvider.searchTerm.isNotEmpty) {
|
||||
return MihSingleChildScroll(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.iDontKnow,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Text(
|
||||
"Let's try refining your search",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else if (directoryProvider.searchedBusinesses.isEmpty &&
|
||||
directoryProvider.searchTerm.isEmpty) {
|
||||
return MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.businessProfile,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Search for businesses of Mzansi!",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
Icons.swap_horiz_rounded,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(text: " to search for people of Mzansi"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
Icons.filter_list_rounded,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(text: " to filter business types"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Center(
|
||||
child: Text(
|
||||
"Error pulling Patients Data\n/users/search/${directoryProvider.searchTerm}",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget displayPersonalSearchResults(
|
||||
MzansiDirectoryProvider directoryProvider) {
|
||||
if (loadingSearchResults) {
|
||||
return Center(
|
||||
child: const Mihloadingcircle(),
|
||||
);
|
||||
} else if (directoryProvider.searchedUsers.isNotEmpty) {
|
||||
directoryProvider.searchedUsers
|
||||
.sort((a, b) => a.username.compareTo(b.username));
|
||||
return BuildUserSearchResultsList(
|
||||
userList: directoryProvider.searchedUsers);
|
||||
} else if (directoryProvider.searchedUsers.isEmpty &&
|
||||
directoryProvider.searchTerm.isEmpty) {
|
||||
return MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.personalProfile,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Search for people of Mzansi!",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
Icons.swap_horiz_rounded,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(text: " to search for businesses of Mzansi"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
} else if (directoryProvider.searchedUsers.isEmpty &&
|
||||
directoryProvider.searchTerm.isNotEmpty) {
|
||||
return MihSingleChildScroll(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.iDontKnow,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Let's try refining your search",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Center(
|
||||
child: Text(
|
||||
"Error pulling Patients Data\n/users/search/${directoryProvider.searchTerm}",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/business_employee.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_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_edit_employee_details_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class BuildEmployeeList extends StatefulWidget {
|
||||
const BuildEmployeeList({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildEmployeeList> createState() => _BuildEmployeeListState();
|
||||
}
|
||||
|
||||
class _BuildEmployeeListState extends State<BuildEmployeeList> {
|
||||
final baseAPI = AppEnviroment.baseApiUrl;
|
||||
|
||||
void updateEmployeePopUp(BusinessEmployee employee) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MihEditEmployeeDetailsWindow(
|
||||
employee: employee,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return ListView.separated(
|
||||
separatorBuilder: (BuildContext context, index) {
|
||||
return Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
},
|
||||
itemCount: mzansiProfileProvider.employeeList!.length,
|
||||
itemBuilder: (context, index) {
|
||||
//final patient = widget.patients[index].id_no.contains(widget.searchString);
|
||||
//print(index);
|
||||
BusinessEmployee employee =
|
||||
mzansiProfileProvider.employeeList![index];
|
||||
String isMe = "";
|
||||
if (mzansiProfileProvider.user!.app_id ==
|
||||
mzansiProfileProvider.employeeList![index].app_id) {
|
||||
isMe = "(You)";
|
||||
}
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"${mzansiProfileProvider.employeeList![index].fname} ${mzansiProfileProvider.employeeList![index].lname} - ${mzansiProfileProvider.employeeList![index].title} $isMe"),
|
||||
subtitle: Text(
|
||||
"${mzansiProfileProvider.employeeList![index].username}\n${mzansiProfileProvider.employeeList![index].email}\nAccess: ${mzansiProfileProvider.employeeList![index].access}",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
updateEmployeePopUp(employee);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_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_employee_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class BuildUserList extends StatefulWidget {
|
||||
const BuildUserList({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildUserList> createState() => _BuildUserListState();
|
||||
}
|
||||
|
||||
class _BuildUserListState extends State<BuildUserList> {
|
||||
final baseAPI = AppEnviroment.baseApiUrl;
|
||||
|
||||
String hideEmail(String email) {
|
||||
var firstLetter = email[0];
|
||||
var end = email.split("@")[1];
|
||||
return "$firstLetter********@$end";
|
||||
}
|
||||
|
||||
void addEmployeePopUp(
|
||||
MzansiProfileProvider profileProvider, int index, double width) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MihAddEmployeeWindow(
|
||||
user: profileProvider.userSearchResults[index],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
Widget? child) {
|
||||
return ListView.separated(
|
||||
separatorBuilder: (BuildContext context, index) {
|
||||
return Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
},
|
||||
itemCount: profileProvider.userSearchResults.length,
|
||||
itemBuilder: (context, index) {
|
||||
var isYou = "";
|
||||
if (profileProvider.user!.app_id ==
|
||||
profileProvider.userSearchResults[index].app_id) {
|
||||
isYou = "(You)";
|
||||
}
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"@${profileProvider.userSearchResults[index].username} $isYou"),
|
||||
subtitle: Text(
|
||||
"Email: ${hideEmail(profileProvider.userSearchResults[index].email)}",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
addEmployeePopUp(profileProvider, index, screenWidth);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_user_search.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_team.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_user.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_business_employee_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_data_helper_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class BusinesProfile extends StatefulWidget {
|
||||
const BusinesProfile({super.key});
|
||||
|
||||
@override
|
||||
State<BusinesProfile> createState() => _BusinesProfileState();
|
||||
}
|
||||
|
||||
class _BusinesProfileState extends State<BusinesProfile> {
|
||||
bool _isLoadingInitialData = true;
|
||||
late final MihBusinessDetails _businessDetails;
|
||||
late final MihMyBusinessUser _businessUser;
|
||||
late final MihMyBusinessTeam _businessTeam;
|
||||
late final MihBusinessUserSearch _businessUserSearch;
|
||||
late final MihBusinessReviews _businessReviews;
|
||||
late final MihBusinessQrCode _businessQrCode;
|
||||
|
||||
Future<void> _loadInitialData() async {
|
||||
setState(() {
|
||||
_isLoadingInitialData = true;
|
||||
});
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
if (mzansiProfileProvider.user == null) {
|
||||
await MihDataHelperServices().loadUserDataWithBusinessesData(
|
||||
mzansiProfileProvider,
|
||||
);
|
||||
}
|
||||
await MihBusinessEmployeeServices()
|
||||
.fetchEmployees(mzansiProfileProvider, context);
|
||||
setState(() {
|
||||
_isLoadingInitialData = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_businessDetails = MihBusinessDetails();
|
||||
_businessUser = MihMyBusinessUser();
|
||||
_businessTeam = MihMyBusinessTeam();
|
||||
_businessUserSearch = MihBusinessUserSearch();
|
||||
_businessReviews = MihBusinessReviews(business: null);
|
||||
_businessQrCode = MihBusinessQrCode(business: null);
|
||||
_loadInitialData();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
if (_isLoadingInitialData) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Mihloadingcircle(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appToolTitles: getToolTitle(),
|
||||
appBody: getToolBody(),
|
||||
selectedbodyIndex: mzansiProfileProvider.businessIndex,
|
||||
onIndexChange: (newIndex) {
|
||||
mzansiProfileProvider.setBusinessIndex(newIndex);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
mzansiProfileProvider.setHideBusinessUserDetails(true);
|
||||
mzansiProfileProvider.setBusinessIndex(0);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.business)] = () {
|
||||
context.read<MzansiProfileProvider>().setBusinessIndex(0);
|
||||
};
|
||||
temp[const Icon(Icons.person)] = () {
|
||||
context.read<MzansiProfileProvider>().setBusinessIndex(1);
|
||||
};
|
||||
temp[const Icon(Icons.people)] = () {
|
||||
context.read<MzansiProfileProvider>().setBusinessIndex(2);
|
||||
};
|
||||
temp[const Icon(Icons.add)] = () {
|
||||
context
|
||||
.read<MzansiProfileProvider>()
|
||||
.setUserearchResults(userSearchResults: []);
|
||||
context.read<MzansiProfileProvider>().setBusinessIndex(3);
|
||||
};
|
||||
temp[const Icon(Icons.star_rate_rounded)] = () {
|
||||
context.read<MzansiProfileProvider>().setBusinessIndex(4);
|
||||
};
|
||||
temp[const Icon(Icons.qr_code_rounded)] = () {
|
||||
context.read<MzansiProfileProvider>().setBusinessIndex(5);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MzansiProfileProvider>().businessIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Profile",
|
||||
"User",
|
||||
"Team",
|
||||
"Add",
|
||||
"Reviews",
|
||||
"Share",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_businessDetails,
|
||||
_businessUser,
|
||||
_businessTeam,
|
||||
_businessUserSearch,
|
||||
_businessReviews,
|
||||
_businessQrCode,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
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/business.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.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_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_business_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';
|
||||
|
||||
class MihAddBookmarkAlert extends StatefulWidget {
|
||||
final Business business;
|
||||
final void Function()? onSuccessDismissPressed;
|
||||
const MihAddBookmarkAlert({
|
||||
super.key,
|
||||
required this.business,
|
||||
required this.onSuccessDismissPressed,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihAddBookmarkAlert> createState() => _MihAddBookmarkAlertState();
|
||||
}
|
||||
|
||||
class _MihAddBookmarkAlertState extends State<MihAddBookmarkAlert> {
|
||||
Future<void> getFavouriteBusinesses() async {
|
||||
MzansiDirectoryProvider directoryProvider =
|
||||
context.read<MzansiDirectoryProvider>();
|
||||
MzansiProfileProvider profileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
await MihMzansiDirectoryServices().getAllUserBookmarkedBusiness(
|
||||
profileProvider.user!.app_id,
|
||||
directoryProvider,
|
||||
);
|
||||
List<Business> favBus = [];
|
||||
Map<String, Future<String>> favBusImages = {};
|
||||
Future<String> businessLogoUrl;
|
||||
for (var bus in directoryProvider.bookmarkedBusinesses) {
|
||||
await MihBusinessDetailsServices()
|
||||
.getBusinessDetailsByBusinessId(bus.business_id)
|
||||
.then((business) async {
|
||||
favBus.add(business!);
|
||||
businessLogoUrl = MihFileApi.getMinioFileUrl(business.logo_path);
|
||||
favBusImages[business.business_id] = businessLogoUrl;
|
||||
});
|
||||
}
|
||||
directoryProvider.setFavouriteBusinesses(
|
||||
businesses: favBus,
|
||||
businessesImagesUrl: favBusImages,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> addBookmark(
|
||||
MzansiProfileProvider profileProvider, String business_id) async {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
await MihMzansiDirectoryServices()
|
||||
.addBookmarkedBusiness(profileProvider.user!.app_id, business_id)
|
||||
.then((statusCode) {
|
||||
context.pop();
|
||||
if (statusCode == 201) {
|
||||
successPopUp(
|
||||
"Successfully Bookmarked Business!",
|
||||
"${widget.business.Name} has successfully been added to favourite businessess in the Mzansi Directory.",
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().errorBasicAlert(
|
||||
"Error Adding Bookmark",
|
||||
"An error occured while add ${widget.business.Name} to you Mzansi Directory, Please try again later.",
|
||||
context,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void successPopUp(String title, String message) {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
title,
|
||||
message,
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () async {
|
||||
await getFavouriteBusinesses();
|
||||
widget.onSuccessDismissPressed!.call();
|
||||
context.pop();
|
||||
context.pop();
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
Widget? child) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: null,
|
||||
onWindowTapClose: null,
|
||||
backgroundColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
windowBody: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.warning_rounded,
|
||||
size: 150,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
Text(
|
||||
"Bookmark Business",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Text(
|
||||
"Are you sure you want to save ${widget.business.Name} to your Mzansi Directory?",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
width: 300,
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
width: 300,
|
||||
onPressed: () {
|
||||
addBookmark(profileProvider, widget.business.business_id);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: Text(
|
||||
"Bookmark Business",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
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/app_user.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_business_employee_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihAddEmployeeWindow extends StatefulWidget {
|
||||
final AppUser user;
|
||||
const MihAddEmployeeWindow({
|
||||
super.key,
|
||||
required this.user,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihAddEmployeeWindow> createState() => _MihAddEmployeeWindowState();
|
||||
}
|
||||
|
||||
class _MihAddEmployeeWindowState extends State<MihAddEmployeeWindow> {
|
||||
TextEditingController accessController = TextEditingController();
|
||||
TextEditingController usernameController = TextEditingController();
|
||||
TextEditingController emailController = TextEditingController();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
Future<void> createBusinessUserAPICall(
|
||||
MzansiProfileProvider mzansiProfileProvider) async {
|
||||
int statusCode = await MihBusinessEmployeeServices().addEmployee(
|
||||
mzansiProfileProvider,
|
||||
widget.user,
|
||||
accessController.text,
|
||||
context,
|
||||
);
|
||||
if (statusCode == 201) {
|
||||
String message =
|
||||
"${widget.user.username} is now apart of your team with ${accessController.text} access to ${mzansiProfileProvider.business!.Name}";
|
||||
successPopUp(message, false);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
void successPopUp(String message, bool stayOnPersonalSide) {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
"Successfully Added Employee",
|
||||
message,
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
context.pop();
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
bool isRequiredFieldsCaptured() {
|
||||
if (accessController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
accessController.dispose();
|
||||
usernameController.dispose();
|
||||
emailController.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
usernameController.text = widget.user.username;
|
||||
emailController.text = widget.user.email;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Add Employee",
|
||||
windowBody: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: screenWidth * 0.05)
|
||||
: const EdgeInsets.symmetric(horizontal: 0),
|
||||
child: Column(
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: usernameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Username",
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: emailController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Email",
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihDropdownField(
|
||||
controller: accessController,
|
||||
hintText: "Access Type",
|
||||
dropdownOptions: const ["Full", "Partial"],
|
||||
editable: true,
|
||||
enableSearch: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
requiredText: true,
|
||||
),
|
||||
const SizedBox(height: 15.0),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
if (isRequiredFieldsCaptured()) {
|
||||
createBusinessUserAPICall(mzansiProfileProvider);
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Add",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onWindowTapClose: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
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_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.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_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';
|
||||
|
||||
class MihDeleteBookmarkAlert extends StatefulWidget {
|
||||
final Business business;
|
||||
final BookmarkedBusiness? bookmarkBusiness;
|
||||
final void Function()? onSuccessDismissPressed;
|
||||
// final String? startUpSearch;
|
||||
const MihDeleteBookmarkAlert({
|
||||
super.key,
|
||||
required this.business,
|
||||
required this.bookmarkBusiness,
|
||||
required this.onSuccessDismissPressed,
|
||||
// required this.startUpSearch,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihDeleteBookmarkAlert> createState() => _MihDeleteBookmarkAlertState();
|
||||
}
|
||||
|
||||
class _MihDeleteBookmarkAlertState extends State<MihDeleteBookmarkAlert> {
|
||||
Future<void> getFavouriteBusinesses() async {
|
||||
MzansiDirectoryProvider directoryProvider =
|
||||
context.read<MzansiDirectoryProvider>();
|
||||
MzansiProfileProvider profileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
await MihMzansiDirectoryServices().getAllUserBookmarkedBusiness(
|
||||
profileProvider.user!.app_id,
|
||||
directoryProvider,
|
||||
);
|
||||
List<Business> favBus = [];
|
||||
Map<String, Future<String>> favBusImages = {};
|
||||
Future<String> businessLogoUrl;
|
||||
for (var bus in directoryProvider.bookmarkedBusinesses) {
|
||||
await MihBusinessDetailsServices()
|
||||
.getBusinessDetailsByBusinessId(bus.business_id)
|
||||
.then((business) async {
|
||||
favBus.add(business!);
|
||||
businessLogoUrl = MihFileApi.getMinioFileUrl(business.logo_path);
|
||||
favBusImages[business.business_id] = businessLogoUrl;
|
||||
});
|
||||
}
|
||||
directoryProvider.setFavouriteBusinesses(
|
||||
businesses: favBus,
|
||||
businessesImagesUrl: favBusImages,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteBookmark(int idbookmarked_businesses) async {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
await MihMzansiDirectoryServices()
|
||||
.deleteBookmarkedBusiness(idbookmarked_businesses)
|
||||
.then((statusCode) {
|
||||
context.pop();
|
||||
if (statusCode == 200) {
|
||||
successPopUp(
|
||||
"Successfully Removed Bookmark!",
|
||||
"${widget.business.Name} has successfully been removed your favourite businessess in the Mzansi Directory.",
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().errorBasicAlert(
|
||||
"Error Adding Bookmark",
|
||||
"An error occured while add ${widget.business.Name} to you Mzansi Directory, Please try again later.",
|
||||
context,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void successPopUp(String title, String message) {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
title,
|
||||
message,
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () async {
|
||||
await getFavouriteBusinesses();
|
||||
widget.onSuccessDismissPressed!.call();
|
||||
context.pop();
|
||||
context.pop();
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: null,
|
||||
onWindowTapClose: null,
|
||||
backgroundColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
windowBody: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.warning_rounded,
|
||||
size: 150,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
Text(
|
||||
"Remove Bookmark",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Text(
|
||||
"Are you sure you want to remove ${widget.business.Name} from your Mzansi Directory?",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
width: 300,
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
width: 300,
|
||||
onPressed: () {
|
||||
// todo: remove bookmark
|
||||
deleteBookmark(
|
||||
widget.bookmarkBusiness!.idbookmarked_businesses);
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: Text(
|
||||
"Remove Business",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/business_employee.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_business_employee_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihEditEmployeeDetailsWindow extends StatefulWidget {
|
||||
final BusinessEmployee employee;
|
||||
const MihEditEmployeeDetailsWindow({
|
||||
super.key,
|
||||
required this.employee,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihEditEmployeeDetailsWindow> createState() =>
|
||||
_MihEditEmployeeDetailsWindowState();
|
||||
}
|
||||
|
||||
class _MihEditEmployeeDetailsWindowState
|
||||
extends State<MihEditEmployeeDetailsWindow> {
|
||||
TextEditingController accessController = TextEditingController();
|
||||
TextEditingController titleController = TextEditingController();
|
||||
TextEditingController fnameController = TextEditingController();
|
||||
TextEditingController lnameController = TextEditingController();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
void updateEmployeeAPICall(
|
||||
MzansiProfileProvider mzansiProfileProvider) async {
|
||||
int statusCode = await MihBusinessEmployeeServices().updateEmployeeDetails(
|
||||
mzansiProfileProvider,
|
||||
widget.employee,
|
||||
titleController.text,
|
||||
accessController.text,
|
||||
context);
|
||||
if (statusCode == 200) {
|
||||
String message = "Your employees details have been updated.";
|
||||
successPopUp(message, false);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteEmployeeApiCall() async {
|
||||
int statusCode = await MihBusinessEmployeeServices().deleteEmployee(
|
||||
context.read<MzansiProfileProvider>(),
|
||||
widget.employee,
|
||||
context,
|
||||
);
|
||||
if (statusCode == 200) {
|
||||
String message =
|
||||
"The employee has been deleted successfully. This means they will no longer have access to your business profile";
|
||||
context.pop();
|
||||
successPopUp(message, false);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
void showDeleteWarning() {
|
||||
MihAlertServices().deleteConfirmationAlert(
|
||||
"This team member will be deleted permanently from the business profile. Are you certain you want to delete it?",
|
||||
() {
|
||||
deleteEmployeeApiCall();
|
||||
},
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
void successPopUp(String message, bool stayOnPersonalSide) {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
"Successfully Updated Employee Details",
|
||||
message,
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
context.pop();
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
bool isRequiredFieldsCaptured() {
|
||||
if (accessController.text.isEmpty || titleController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
accessController.dispose();
|
||||
titleController.dispose();
|
||||
fnameController.dispose();
|
||||
lnameController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
fnameController.text = widget.employee.fname;
|
||||
lnameController.text = widget.employee.lname;
|
||||
titleController.text = widget.employee.title;
|
||||
accessController.text = widget.employee.access;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Employee Details",
|
||||
menuOptions: [
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.delete,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Delete Employee",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
showDeleteWarning();
|
||||
},
|
||||
),
|
||||
],
|
||||
onWindowTapClose: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
windowBody: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: screenWidth * 0.05)
|
||||
: const EdgeInsets.symmetric(horizontal: 0),
|
||||
child: Column(
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: fnameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "First Name",
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: lnameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Surname",
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: titleController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Title",
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihDropdownField(
|
||||
controller: accessController,
|
||||
hintText: "Access Type",
|
||||
dropdownOptions: const ["Full", "Partial"],
|
||||
editable: true,
|
||||
enableSearch: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
requiredText: true,
|
||||
),
|
||||
const SizedBox(height: 20.0),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
if (isRequiredFieldsCaptured()) {
|
||||
updateEmployeeAPICall(mzansiProfileProvider);
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Update",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,550 @@
|
||||
import 'package:custom_rating_bar/custom_rating_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_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_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihReviewBusinessWindow extends StatefulWidget {
|
||||
final Business business;
|
||||
final BusinessReview? businessReview;
|
||||
final double screenWidth;
|
||||
final bool readOnly;
|
||||
final void Function()? onSuccessDismissPressed;
|
||||
const MihReviewBusinessWindow({
|
||||
super.key,
|
||||
required this.business,
|
||||
required this.businessReview,
|
||||
required this.screenWidth,
|
||||
required this.readOnly,
|
||||
required this.onSuccessDismissPressed,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihReviewBusinessWindow> createState() =>
|
||||
_MihReviewBusinessWindowState();
|
||||
}
|
||||
|
||||
class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final TextEditingController _reviewTitleController = TextEditingController();
|
||||
final TextEditingController _reviewScoreController = TextEditingController();
|
||||
final TextEditingController _reviewReviewerController =
|
||||
TextEditingController();
|
||||
final TextEditingController _reviewDescriptionController =
|
||||
TextEditingController();
|
||||
late final VoidCallback _reviewDescriptionListener;
|
||||
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
|
||||
|
||||
void showDeleteReviewAlert(MzansiDirectoryProvider directoryProvider) {
|
||||
MihAlertServices().errorAdvancedAlert(
|
||||
"Delete Review",
|
||||
"Are you sure you want to delete this review? This action cannot be undone.",
|
||||
[
|
||||
MihButton(
|
||||
width: 300,
|
||||
onPressed: () async {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
await MihMzansiDirectoryServices()
|
||||
.deleteBusinessReview(
|
||||
widget.businessReview!.idbusiness_ratings,
|
||||
widget.businessReview!.business_id,
|
||||
widget.businessReview!.rating_score,
|
||||
widget.business.rating,
|
||||
)
|
||||
.then((statusCode) async {
|
||||
context.pop(); //Remove loading dialog
|
||||
context.pop(); //Remove delete dialog
|
||||
if (statusCode == 200) {
|
||||
await refreshBusiness(directoryProvider);
|
||||
successPopUp(
|
||||
"Successfully Deleted Review!",
|
||||
"Your review has successfully been delete and will no longer appear under the business.",
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().errorBasicAlert(
|
||||
"Error Deleting Review",
|
||||
"There was an error deleting your review. Please try again later.",
|
||||
context,
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: Text(
|
||||
"Delete",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
width: 300,
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
Color getMissionVisionLimitColor(int limit) {
|
||||
if (_counter.value <= limit) {
|
||||
return MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
} else {
|
||||
return MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> refreshBusiness(
|
||||
MzansiDirectoryProvider directoryProvider) async {
|
||||
Business? refresedBusiness = await MihBusinessDetailsServices()
|
||||
.getBusinessDetailsByBusinessId(widget.business.business_id);
|
||||
if (refresedBusiness != null) {
|
||||
directoryProvider.setSelectedBusiness(business: refresedBusiness);
|
||||
}
|
||||
}
|
||||
|
||||
void submitForm(
|
||||
MzansiProfileProvider profileProvider,
|
||||
MzansiDirectoryProvider directoryProvider,
|
||||
) async {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle();
|
||||
},
|
||||
);
|
||||
if (widget.businessReview != null) {
|
||||
await MihMzansiDirectoryServices()
|
||||
.updateBusinessReview(
|
||||
widget.businessReview!.idbusiness_ratings,
|
||||
widget.businessReview!.business_id,
|
||||
_reviewTitleController.text,
|
||||
_reviewDescriptionController.text,
|
||||
_reviewScoreController.text,
|
||||
widget.businessReview!.rating_score,
|
||||
widget.business.rating,
|
||||
)
|
||||
.then((statusCode) async {
|
||||
context.pop(); //Remove loading dialog
|
||||
if (statusCode == 200) {
|
||||
await refreshBusiness(directoryProvider);
|
||||
successPopUp(
|
||||
"Successfully Updated Review!",
|
||||
"Your review has successfully been updated and will now appear under the business.",
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().errorBasicAlert(
|
||||
"Error Updating Review",
|
||||
"There was an error updating your review. Please try again later.",
|
||||
context,
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await MihMzansiDirectoryServices()
|
||||
.addBusinessReview(
|
||||
profileProvider.user!.app_id,
|
||||
widget.business.business_id,
|
||||
_reviewTitleController.text,
|
||||
_reviewDescriptionController.text,
|
||||
_reviewScoreController.text,
|
||||
widget.business.rating.isEmpty ? "0.0" : widget.business.rating,
|
||||
)
|
||||
.then((statusCode) async {
|
||||
context.pop(); //Remove loading dialog
|
||||
if (statusCode == 201) {
|
||||
await refreshBusiness(directoryProvider);
|
||||
successPopUp(
|
||||
"Successfully Added Review!",
|
||||
"Your review has successfully been added and will now appear under the business.",
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().errorBasicAlert(
|
||||
"Error Adding Review",
|
||||
"There was an error adding your review. Please try again later.",
|
||||
context,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void successPopUp(String title, String message) {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
title,
|
||||
message,
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
context.pop();
|
||||
widget.onSuccessDismissPressed!.call();
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
String getWindowTitle() {
|
||||
if (widget.readOnly) {
|
||||
return "Review Details";
|
||||
} else if (widget.businessReview != null) {
|
||||
return "Update Review";
|
||||
} else {
|
||||
return "Add Review";
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
_reviewDescriptionController.removeListener(_reviewDescriptionListener);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_reviewDescriptionListener = () {
|
||||
setState(() {
|
||||
_counter.value = _reviewDescriptionController.text.characters.length;
|
||||
});
|
||||
};
|
||||
_reviewDescriptionController.addListener(_reviewDescriptionListener);
|
||||
if (widget.businessReview != null) {
|
||||
setState(() {
|
||||
_reviewTitleController.text = widget.businessReview!.rating_title;
|
||||
_reviewDescriptionController.text =
|
||||
widget.businessReview!.rating_description;
|
||||
_reviewScoreController.text = widget.businessReview!.rating_score;
|
||||
_reviewReviewerController.text = widget.businessReview!.reviewer;
|
||||
});
|
||||
} else {
|
||||
_reviewScoreController.text = "1.0"; // Default score
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// return const Placeholder();
|
||||
return Consumer2<MzansiProfileProvider, MzansiDirectoryProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
MzansiDirectoryProvider directoryProvider, Widget? child) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: getWindowTitle(),
|
||||
onWindowTapClose: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
menuOptions: widget.businessReview != null && !widget.readOnly
|
||||
? [
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.delete,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
label: "Delete Review",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
showDeleteReviewAlert(directoryProvider);
|
||||
},
|
||||
),
|
||||
]
|
||||
: null,
|
||||
windowBody: MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding: MzansiInnovationHub.of(context)!.theme.screenType ==
|
||||
"desktop"
|
||||
? EdgeInsets.symmetric(horizontal: widget.screenWidth * 0.05)
|
||||
: EdgeInsets.symmetric(horizontal: widget.screenWidth * 0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
"Business Rating",
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
widget.readOnly
|
||||
? RatingBar.readOnly(
|
||||
size: 50,
|
||||
alignment: Alignment.centerLeft,
|
||||
filledIcon: Icons.star,
|
||||
emptyIcon: Icons.star_border,
|
||||
halfFilledIcon: Icons.star_half,
|
||||
filledColor: MihColors.getYellowColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
// filledColor: MzansiInnovationHub.of(context)!
|
||||
// .theme
|
||||
// .secondaryColor(),
|
||||
emptyColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
halfFilledColor: MihColors.getYellowColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
// MzansiInnovationHub.of(context)!
|
||||
// .theme
|
||||
// .secondaryColor(),
|
||||
isHalfAllowed: true,
|
||||
initialRating: widget.businessReview != null
|
||||
? double.parse(_reviewScoreController.text)
|
||||
: 1,
|
||||
maxRating: 5,
|
||||
)
|
||||
: RatingBar(
|
||||
size: 50,
|
||||
alignment: Alignment.centerLeft,
|
||||
filledIcon: Icons.star,
|
||||
emptyIcon: Icons.star_border,
|
||||
halfFilledIcon: Icons.star_half,
|
||||
filledColor: MihColors.getYellowColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
emptyColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
halfFilledColor: MihColors.getYellowColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
isHalfAllowed: true,
|
||||
initialRating: widget.businessReview != null
|
||||
? double.parse(_reviewScoreController.text)
|
||||
: 1,
|
||||
maxRating: 5,
|
||||
onRatingChanged: (double) {
|
||||
setState(() {
|
||||
_reviewScoreController.text =
|
||||
double.toStringAsFixed(1);
|
||||
});
|
||||
print(_reviewScoreController.text);
|
||||
},
|
||||
),
|
||||
Visibility(
|
||||
visible: widget.readOnly,
|
||||
child: const SizedBox(height: 10),
|
||||
),
|
||||
Visibility(
|
||||
visible: widget.readOnly,
|
||||
child: MihTextFormField(
|
||||
// width: 200,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: _reviewReviewerController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Reviewer",
|
||||
validator: (value) {
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
// width: 200,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: _reviewTitleController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: widget.readOnly,
|
||||
hintText: "Review Title",
|
||||
validator: (value) {
|
||||
return MihValidationServices()
|
||||
.isEmpty(_reviewTitleController.text);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
height: 250,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: _reviewDescriptionController,
|
||||
multiLineInput: true,
|
||||
requiredText: widget.readOnly,
|
||||
readOnly: widget.readOnly,
|
||||
hintText: "Review Description",
|
||||
validator: (value) {
|
||||
if (_reviewDescriptionController.text.isEmpty) {
|
||||
return null;
|
||||
} else {
|
||||
return MihValidationServices().validateLength(
|
||||
_reviewDescriptionController.text, 256);
|
||||
}
|
||||
},
|
||||
),
|
||||
Visibility(
|
||||
visible: !widget.readOnly,
|
||||
child: SizedBox(
|
||||
height: 15,
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: _counter,
|
||||
builder: (BuildContext context, int value,
|
||||
Widget? child) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
"$value",
|
||||
style: TextStyle(
|
||||
color: getMissionVisionLimitColor(256),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
"/256",
|
||||
style: TextStyle(
|
||||
color: getMissionVisionLimitColor(256),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Visibility(
|
||||
visible: !widget.readOnly,
|
||||
child: Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitForm(
|
||||
profileProvider,
|
||||
directoryProvider,
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
widget.businessReview != null
|
||||
? "Update Review"
|
||||
: "Add Review",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,620 @@
|
||||
import 'package:country_code_picker/country_code_picker.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_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_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihUpdateBusinessDetailsWindow extends StatefulWidget {
|
||||
final double width;
|
||||
const MihUpdateBusinessDetailsWindow({
|
||||
super.key,
|
||||
required this.width,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihUpdateBusinessDetailsWindow> createState() =>
|
||||
_MihUpdateBusinessDetailsWindowState();
|
||||
}
|
||||
|
||||
class _MihUpdateBusinessDetailsWindowState
|
||||
extends State<MihUpdateBusinessDetailsWindow> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
PlatformFile? newSelectedLogoPic;
|
||||
final fileNameController = TextEditingController();
|
||||
final regController = TextEditingController();
|
||||
final nameController = TextEditingController();
|
||||
final typeController = TextEditingController();
|
||||
final practiceNoController = TextEditingController();
|
||||
final vatNoController = TextEditingController();
|
||||
final countryCodeController = TextEditingController();
|
||||
final contactController = TextEditingController();
|
||||
final emailController = TextEditingController();
|
||||
final locationController = TextEditingController();
|
||||
final websiteController = TextEditingController();
|
||||
final ratingController = TextEditingController();
|
||||
final missionVisionController = TextEditingController();
|
||||
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
|
||||
late String env;
|
||||
|
||||
void setContactNumberControllers(
|
||||
MzansiProfileProvider mzansiProfileProvider) {
|
||||
if (mzansiProfileProvider.business!.contact_no[0] == "+") {
|
||||
List<String> contactDetails =
|
||||
mzansiProfileProvider.business!.contact_no.split("-");
|
||||
setState(() {
|
||||
countryCodeController.text = contactDetails[0];
|
||||
contactController.text = contactDetails[1];
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
countryCodeController.text = "+27";
|
||||
contactController.text = mzansiProfileProvider.business!.contact_no;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void setControllers() {
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
setState(() {
|
||||
fileNameController.text =
|
||||
mzansiProfileProvider.business!.logo_path.split("/").last;
|
||||
regController.text = mzansiProfileProvider.business!.registration_no;
|
||||
nameController.text = mzansiProfileProvider.business!.Name;
|
||||
typeController.text = mzansiProfileProvider.business!.type;
|
||||
practiceNoController.text = mzansiProfileProvider.business!.practice_no;
|
||||
vatNoController.text = mzansiProfileProvider.business!.vat_no;
|
||||
emailController.text = mzansiProfileProvider.business!.bus_email;
|
||||
locationController.text = mzansiProfileProvider.business!.gps_location;
|
||||
websiteController.text = mzansiProfileProvider.business!.website;
|
||||
ratingController.text = mzansiProfileProvider.business!.rating;
|
||||
missionVisionController.text =
|
||||
mzansiProfileProvider.business!.mission_vision;
|
||||
});
|
||||
setContactNumberControllers(mzansiProfileProvider);
|
||||
if (AppEnviroment.getEnv() == "Prod") {
|
||||
env = "Prod";
|
||||
} else {
|
||||
env = "Dev";
|
||||
}
|
||||
}
|
||||
|
||||
Color getMissionVisionLimitColor(int limit) {
|
||||
if (_counter.value <= limit) {
|
||||
return MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
} else {
|
||||
return MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
}
|
||||
}
|
||||
|
||||
void _updateMissionVisionCounter() {
|
||||
// New function name
|
||||
// No need for setState since you are using a ValueNotifier for _counter
|
||||
_counter.value = missionVisionController.text.characters.length;
|
||||
}
|
||||
|
||||
String getNumberWithCountryCode() {
|
||||
String numberWithoutBeginingZero = "";
|
||||
if (contactController.text[0] == "0") {
|
||||
numberWithoutBeginingZero = contactController.text
|
||||
.replaceAll(" ", "")
|
||||
.substring(1, contactController.text.length);
|
||||
} else {
|
||||
numberWithoutBeginingZero = contactController.text.replaceAll("-", " ");
|
||||
}
|
||||
return "${countryCodeController.text}-$numberWithoutBeginingZero";
|
||||
}
|
||||
|
||||
bool isFormFilled() {
|
||||
if (typeController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void successPopUp(String message, bool stayOnPersonalSide) {
|
||||
MihAlertServices().successBasicAlert(
|
||||
"Success!",
|
||||
message,
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> uploadFile(MzansiProfileProvider mzansiProfileProvider) async {
|
||||
if (newSelectedLogoPic != null) {
|
||||
int uploadStatusCode = 0;
|
||||
uploadStatusCode = await MihFileApi.uploadFile(
|
||||
mzansiProfileProvider.business!.business_id,
|
||||
env,
|
||||
"business_files",
|
||||
newSelectedLogoPic!,
|
||||
context,
|
||||
);
|
||||
if (uploadStatusCode == 200) {
|
||||
int deleteStatusCode = 0;
|
||||
deleteStatusCode = await MihFileApi.deleteFile(
|
||||
mzansiProfileProvider.business!.logo_path.split("/").first,
|
||||
env,
|
||||
"business_files",
|
||||
mzansiProfileProvider.business!.logo_path.split("/").last,
|
||||
context,
|
||||
);
|
||||
if (deleteStatusCode == 200) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true; // No file selected, so no upload needed
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> submitForm(MzansiProfileProvider mzansiProfileProvider) async {
|
||||
KenLogger.success("Start Submit Form");
|
||||
if (isFormFilled()) {
|
||||
KenLogger.success("Form Filled");
|
||||
KenLogger.success("Start File Upload");
|
||||
bool successfullyUploadedFile = await uploadFile(mzansiProfileProvider);
|
||||
KenLogger.success(
|
||||
"File Upload Complete: outcome $successfullyUploadedFile");
|
||||
if (!mounted) return;
|
||||
KenLogger.success("is mounted");
|
||||
if (successfullyUploadedFile) {
|
||||
KenLogger.success("Start Details Update");
|
||||
int statusCode = 0;
|
||||
statusCode = await MihBusinessDetailsServices().updateBusinessDetailsV2(
|
||||
mzansiProfileProvider.business!.business_id,
|
||||
nameController.text,
|
||||
typeController.text,
|
||||
regController.text,
|
||||
practiceNoController.text,
|
||||
vatNoController.text,
|
||||
emailController.text,
|
||||
getNumberWithCountryCode(),
|
||||
// contactController.text,
|
||||
locationController.text,
|
||||
fileNameController.text,
|
||||
websiteController.text,
|
||||
ratingController.text.isEmpty ? "0" : ratingController.text,
|
||||
missionVisionController.text,
|
||||
mzansiProfileProvider,
|
||||
context,
|
||||
);
|
||||
KenLogger.success("Details Update Complete: status code $statusCode");
|
||||
if (!mounted) return;
|
||||
KenLogger.success("is mounted");
|
||||
if (statusCode == 200) {
|
||||
KenLogger.success("Start Success Message");
|
||||
//You left of here
|
||||
String message = "Your information has been updated successfully!";
|
||||
context.pop();
|
||||
successPopUp(message, false);
|
||||
// File uploaded successfully
|
||||
} else {
|
||||
context.pop();
|
||||
// File upload failed
|
||||
MihAlertServices().errorBasicAlert(
|
||||
"Error Updating Business Details",
|
||||
"An error occurred while updating the business details. Please try again.",
|
||||
context,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
context.pop();
|
||||
if (!mounted) return;
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
setControllers();
|
||||
missionVisionController.addListener(_updateMissionVisionCounter);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: 'Edit Profile',
|
||||
onWindowTapClose: () {
|
||||
context.pop();
|
||||
},
|
||||
windowBody: MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: widget.width * 0.05)
|
||||
: EdgeInsets.symmetric(horizontal: widget.width * 0),
|
||||
child: Column(
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
Center(
|
||||
child: MihCircleAvatar(
|
||||
imageFile: newSelectedLogoPic != null
|
||||
? MemoryImage(newSelectedLogoPic!.bytes!)
|
||||
: mzansiProfileProvider.businessProfilePicture,
|
||||
width: 150,
|
||||
editable: true,
|
||||
fileNameController: fileNameController,
|
||||
userSelectedfile: newSelectedLogoPic,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onChange: (selectedfile) {
|
||||
setState(() {
|
||||
newSelectedLogoPic = selectedfile;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: false,
|
||||
child: MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: fileNameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Selected File Name",
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: nameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Business Name",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: typeController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Business Type",
|
||||
validator: (value) {
|
||||
return MihValidationServices()
|
||||
.validateNoSpecialChars(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: emailController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Business Email",
|
||||
validator: (value) {
|
||||
return MihValidationServices().validateEmail(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
width: 300,
|
||||
alignment: Alignment.topLeft,
|
||||
child: const Text(
|
||||
"Contact Number:",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
CountryCodePicker(
|
||||
padding: EdgeInsetsGeometry.all(0),
|
||||
onChanged: (selectedCode) {
|
||||
setState(() {
|
||||
countryCodeController.text =
|
||||
selectedCode.toString();
|
||||
});
|
||||
debugPrint(
|
||||
"Selected Country Code: ${countryCodeController.text}");
|
||||
},
|
||||
initialSelection: countryCodeController.text,
|
||||
showDropDownButton: false,
|
||||
pickerStyle: PickerStyle.bottomSheet,
|
||||
dialogBackgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
barrierColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
Expanded(
|
||||
child: MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: contactController,
|
||||
numberMode: true,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: null,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
height: 250,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: missionVisionController,
|
||||
multiLineInput: true,
|
||||
requiredText: true,
|
||||
hintText: "Business Mission & Vision",
|
||||
validator: (value) {
|
||||
return MihValidationServices().validateLength(
|
||||
missionVisionController.text, 256);
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
height: 15,
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: _counter,
|
||||
builder:
|
||||
(BuildContext context, int value, Widget? child) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
"$value",
|
||||
style: TextStyle(
|
||||
color: getMissionVisionLimitColor(256),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
"/256",
|
||||
style: TextStyle(
|
||||
color: getMissionVisionLimitColor(256),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: websiteController,
|
||||
multiLineInput: false,
|
||||
requiredText: false,
|
||||
hintText: "Business Website",
|
||||
validator: (value) {
|
||||
return MihValidationServices()
|
||||
.validateWebsite(value, false);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: regController,
|
||||
multiLineInput: false,
|
||||
requiredText: false,
|
||||
hintText: "Registration No.",
|
||||
validator: (value) {
|
||||
// return MihValidationServices().isEmpty(value);
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: practiceNoController,
|
||||
multiLineInput: false,
|
||||
requiredText: false,
|
||||
hintText: "Practice Number",
|
||||
validator: (validateValue) {
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: vatNoController,
|
||||
multiLineInput: false,
|
||||
requiredText: false,
|
||||
hintText: "VAT Number",
|
||||
validator: (value) {
|
||||
// return MihValidationServices().isEmpty(value);
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Flexible(
|
||||
child: MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: locationController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "GPS Location",
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10.0),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle(
|
||||
message: "Getting your location",
|
||||
);
|
||||
},
|
||||
);
|
||||
MIHLocationAPI()
|
||||
.getGPSPosition(context)
|
||||
.then((position) {
|
||||
if (position != null) {
|
||||
setState(() {
|
||||
locationController.text =
|
||||
"${position.latitude}, ${position.longitude}";
|
||||
});
|
||||
}
|
||||
//Dismiss loading indicator
|
||||
context.pop();
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 100,
|
||||
child: Text(
|
||||
"Set",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitForm(mzansiProfileProvider);
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Update",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
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_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.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_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_image_display.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.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_file_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_my_business_user_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihUpdateMyBusinessUserDetails extends StatefulWidget {
|
||||
const MihUpdateMyBusinessUserDetails({super.key});
|
||||
|
||||
@override
|
||||
State<MihUpdateMyBusinessUserDetails> createState() =>
|
||||
_MihUpdateMyBusinessUserDetailsState();
|
||||
}
|
||||
|
||||
class _MihUpdateMyBusinessUserDetailsState
|
||||
extends State<MihUpdateMyBusinessUserDetails> {
|
||||
final fileNameController = TextEditingController();
|
||||
final titleTextController = TextEditingController();
|
||||
final fnameController = TextEditingController();
|
||||
final lnameController = TextEditingController();
|
||||
final accessController = TextEditingController();
|
||||
final signtureController = TextEditingController();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
PlatformFile? userPicFile;
|
||||
PlatformFile? newSelectedSignaturePic;
|
||||
late String env;
|
||||
|
||||
bool isFormFilled() {
|
||||
if (titleTextController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> uploadFile(MzansiProfileProvider mzansiProfileProvider) async {
|
||||
if (newSelectedSignaturePic != null) {
|
||||
int uploadStatusCode = 0;
|
||||
uploadStatusCode = await MihFileApi.uploadFile(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
env,
|
||||
"business_files",
|
||||
newSelectedSignaturePic!,
|
||||
context,
|
||||
);
|
||||
if (uploadStatusCode == 200) {
|
||||
signtureController.text = newSelectedSignaturePic!.name;
|
||||
int deleteStatusCode = 0;
|
||||
deleteStatusCode = await MihFileApi.deleteFile(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
env,
|
||||
"business_files",
|
||||
mzansiProfileProvider.businessUser!.sig_path.split("/").last,
|
||||
context,
|
||||
);
|
||||
if (deleteStatusCode == 200) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true; // No file selected, so no upload needed
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> submitForm(MzansiProfileProvider mzansiProfileProvider) async {
|
||||
if (isFormFilled()) {
|
||||
bool successfullyUploadedFile = await uploadFile(mzansiProfileProvider);
|
||||
if (!mounted) return;
|
||||
if (successfullyUploadedFile) {
|
||||
int statusCode = await MihMyBusinessUserServices().updateBusinessUser(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
mzansiProfileProvider.businessUser!.business_id,
|
||||
titleTextController.text,
|
||||
accessController.text,
|
||||
signtureController.text,
|
||||
mzansiProfileProvider,
|
||||
context,
|
||||
);
|
||||
if (!mounted) return;
|
||||
if (statusCode == 200) {
|
||||
String message = "Business details updated successfully";
|
||||
context.pop();
|
||||
successPopUp(message, false);
|
||||
} else {
|
||||
MihAlertServices().errorBasicAlert(
|
||||
"Error Updating Business User Details",
|
||||
"An error occurred while updating the business User details. Please check internet connection and try again.",
|
||||
context,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
void successPopUp(String message, bool stayOnPersonalSide) {
|
||||
MihAlertServices().successBasicAlert(
|
||||
"Success!",
|
||||
message,
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
Widget getWindowBody(double width) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.2)
|
||||
: EdgeInsets.symmetric(horizontal: width * 0.075),
|
||||
child: Column(
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
Center(
|
||||
child: MihCircleAvatar(
|
||||
imageFile: mzansiProfileProvider.userProfilePicture,
|
||||
width: 150,
|
||||
editable: false,
|
||||
fileNameController: fileNameController,
|
||||
userSelectedfile: userPicFile,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onChange: (_) {},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: false,
|
||||
child: MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: fileNameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Selected File Name",
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: titleTextController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: false,
|
||||
hintText: "Title",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: fnameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "First Name",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: lnameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Surname",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: accessController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Access Level",
|
||||
readOnly: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
width: 300,
|
||||
alignment: Alignment.topLeft,
|
||||
child: const Text(
|
||||
"Signature:",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: MihImageDisplay(
|
||||
imageFile: newSelectedSignaturePic != null
|
||||
? MemoryImage(newSelectedSignaturePic!.bytes!)
|
||||
: mzansiProfileProvider.businessUserSignature,
|
||||
width: 300,
|
||||
height: 200,
|
||||
editable: true,
|
||||
fileNameController: signtureController,
|
||||
userSelectedfile: newSelectedSignaturePic,
|
||||
onChange: (selectedFile) {
|
||||
setState(() {
|
||||
newSelectedSignaturePic = selectedFile;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Visibility(
|
||||
visible: false,
|
||||
child: MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: fileNameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Selected Signature File",
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitForm(mzansiProfileProvider);
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Update",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void setControllers() {
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
fileNameController.text =
|
||||
mzansiProfileProvider.user!.pro_pic_path.split("/").last;
|
||||
signtureController.text =
|
||||
mzansiProfileProvider.businessUser!.sig_path.split("/").last;
|
||||
titleTextController.text = mzansiProfileProvider.businessUser!.title;
|
||||
fnameController.text = mzansiProfileProvider.user!.fname;
|
||||
lnameController.text = mzansiProfileProvider.user!.lname;
|
||||
accessController.text = mzansiProfileProvider.businessUser!.access;
|
||||
if (AppEnviroment.getEnv() == "Prod") {
|
||||
env = "Prod";
|
||||
} else {
|
||||
env = "Dev";
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
fileNameController.dispose();
|
||||
titleTextController.dispose();
|
||||
fnameController.dispose();
|
||||
lnameController.dispose();
|
||||
accessController.dispose();
|
||||
signtureController.dispose();
|
||||
userPicFile = null;
|
||||
newSelectedSignaturePic = null;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
setControllers();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Edit Profile",
|
||||
onWindowTapClose: () {
|
||||
context.pop();
|
||||
},
|
||||
windowBody: getWindowBody(screenWidth),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_view.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MzansiBusinessProfileView extends StatefulWidget {
|
||||
final String? businessId;
|
||||
final bool fromMzansiDirectory;
|
||||
const MzansiBusinessProfileView({
|
||||
super.key,
|
||||
required this.businessId,
|
||||
required this.fromMzansiDirectory,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiBusinessProfileView> createState() =>
|
||||
_MzansiBusinessProfileViewState();
|
||||
}
|
||||
|
||||
class _MzansiBusinessProfileViewState extends State<MzansiBusinessProfileView> {
|
||||
int _selcetedIndex = 0;
|
||||
late final MihBusinessDetailsView _businessDetailsView;
|
||||
late final MihBusinessReviews _businessReviews;
|
||||
late final MihBusinessQrCode _businessQrCode;
|
||||
|
||||
Future<void> _fetchBusinessDetails(
|
||||
MzansiDirectoryProvider directoryProvider) async {
|
||||
if (widget.businessId != null) {
|
||||
final biz = await MihBusinessDetailsServices()
|
||||
.getBusinessDetailsByBusinessId(widget.businessId!);
|
||||
if (biz == null) {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
extra: true,
|
||||
);
|
||||
} else {
|
||||
KenLogger.success("Business found: ${biz.Name}");
|
||||
directoryProvider.setSelectedBusiness(business: biz);
|
||||
}
|
||||
}
|
||||
_businessDetailsView = MihBusinessDetailsView();
|
||||
_businessReviews =
|
||||
MihBusinessReviews(business: directoryProvider.selectedBusiness!);
|
||||
_businessQrCode = MihBusinessQrCode(
|
||||
business: directoryProvider.selectedBusiness!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
MzansiDirectoryProvider directoryProvider =
|
||||
context.read<MzansiDirectoryProvider>();
|
||||
_fetchBusinessDetails(directoryProvider);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiDirectoryProvider>(
|
||||
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
|
||||
Widget? child) {
|
||||
if (directoryProvider.selectedBusiness == null) {
|
||||
KenLogger.warning("Business is null, showing loading indicator");
|
||||
return Scaffold(
|
||||
body: const Center(
|
||||
child: Mihloadingcircle(),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(directoryProvider),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: _selcetedIndex,
|
||||
onIndexChange: (newValue) {
|
||||
setState(() {
|
||||
_selcetedIndex = newValue;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
if (!widget.fromMzansiDirectory) {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
} else {
|
||||
context.pop();
|
||||
}
|
||||
// context.goNamed(
|
||||
// "mzansiDirectory",
|
||||
// );
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.business)] = () {
|
||||
setState(() {
|
||||
_selcetedIndex = 0;
|
||||
});
|
||||
};
|
||||
temp[const Icon(Icons.star_rate_rounded)] = () {
|
||||
setState(() {
|
||||
_selcetedIndex = 1;
|
||||
});
|
||||
};
|
||||
temp[const Icon(Icons.qr_code_rounded)] = () {
|
||||
setState(() {
|
||||
_selcetedIndex = 2;
|
||||
});
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: _selcetedIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody(MzansiDirectoryProvider directoryProvider) {
|
||||
return [
|
||||
_businessDetailsView,
|
||||
_businessReviews,
|
||||
_businessQrCode,
|
||||
];
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Profile",
|
||||
"Reviews",
|
||||
"Share Business",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details_set_up.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MzansiSetUpBusinessProfile extends StatefulWidget {
|
||||
const MzansiSetUpBusinessProfile({super.key});
|
||||
|
||||
@override
|
||||
State<MzansiSetUpBusinessProfile> createState() =>
|
||||
_MzansiSetUpBusinessProfileState();
|
||||
}
|
||||
|
||||
class _MzansiSetUpBusinessProfileState
|
||||
extends State<MzansiSetUpBusinessProfile> {
|
||||
late final MihBusinessDetailsSetUp _businessDetailsSetUp;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_businessDetailsSetUp = MihBusinessDetailsSetUp();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: context.watch<MzansiProfileProvider>().businessIndex,
|
||||
onIndexChange: (newIndex) {
|
||||
context.read<MzansiProfileProvider>().setBusinessIndex(newIndex);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
FocusScope.of(context).unfocus();
|
||||
context.read<MzansiProfileProvider>().setBusinessIndex(0);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.business)] = () {
|
||||
context.read<MzansiProfileProvider>().setBusinessIndex(0);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MzansiProfileProvider>().businessIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Set Up Profile",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_businessDetailsSetUp,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import 'package:go_router/go_router.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_package_components/mih_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MzansiBusinessProfileTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
const MzansiBusinessProfileTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiBusinessProfileTile> createState() =>
|
||||
_MzansiBusinessProfileTileState();
|
||||
}
|
||||
|
||||
class _MzansiBusinessProfileTileState extends State<MzansiBusinessProfileTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageTile(
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
"businessProfileManage",
|
||||
);
|
||||
// Navigator.of(context).pushNamed(
|
||||
// '/business-profile/manage',
|
||||
// arguments: widget.arguments,
|
||||
// );
|
||||
},
|
||||
appName: "Business Profile",
|
||||
appIcon: Icon(
|
||||
MihIcons.businessProfile,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: widget.packageSize,
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import 'package:go_router/go_router.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_package_components/mih_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MzansiSetupBusinessProfileTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
const MzansiSetupBusinessProfileTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiSetupBusinessProfileTile> createState() =>
|
||||
_MzansiSetupBusinessProfileTileState();
|
||||
}
|
||||
|
||||
class _MzansiSetupBusinessProfileTileState
|
||||
extends State<MzansiSetupBusinessProfileTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
MzansiProfileProvider profileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
return MihPackageTile(
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'businessProfileSetup',
|
||||
extra: profileProvider.user,
|
||||
);
|
||||
// Navigator.of(context).pushNamed(
|
||||
// '/business-profile/set-up',
|
||||
// arguments: widget.signedInUser,
|
||||
// );
|
||||
},
|
||||
appName: "Set Up Business",
|
||||
appIcon: Icon(
|
||||
MihIcons.businessSetup,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
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_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_business_info_card.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_update_business_details_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihBusinessDetails extends StatefulWidget {
|
||||
const MihBusinessDetails({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihBusinessDetails> createState() => _MihBusinessDetailsState();
|
||||
}
|
||||
|
||||
class _MihBusinessDetailsState extends State<MihBusinessDetails> {
|
||||
PlatformFile? newSelectedLogoPic;
|
||||
final fileNameController = TextEditingController();
|
||||
|
||||
void editBizProfileWindow(
|
||||
MzansiProfileProvider mzansiProfileProvider, double width) {
|
||||
showDialog(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (context) => MihUpdateBusinessDetailsWindow(width: width),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(screenWidth, context),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width, BuildContext context) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return Stack(
|
||||
children: [
|
||||
MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding: MzansiInnovationHub.of(context)!.theme.screenType ==
|
||||
"desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.2)
|
||||
: EdgeInsets.symmetric(horizontal: width * 0.075),
|
||||
child: Column(
|
||||
children: [
|
||||
Center(
|
||||
child: MihCircleAvatar(
|
||||
key: UniqueKey(),
|
||||
imageFile: mzansiProfileProvider.businessProfilePicture,
|
||||
width: 150,
|
||||
editable: false,
|
||||
fileNameController: fileNameController,
|
||||
userSelectedfile: newSelectedLogoPic,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onChange: (selectedfile) {
|
||||
setState(() {
|
||||
newSelectedLogoPic = selectedfile;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
mzansiProfileProvider.business!.Name,
|
||||
style: TextStyle(
|
||||
fontSize: 35,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
mzansiProfileProvider.business!.type,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: 700,
|
||||
child: Text(
|
||||
mzansiProfileProvider
|
||||
.business!.mission_vision.isNotEmpty
|
||||
? mzansiProfileProvider.business!.mission_vision
|
||||
: "No Mission & Vision added yet",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: MihBusinessCard(
|
||||
business: mzansiProfileProvider.business!,
|
||||
// startUpSearch: null,
|
||||
width: width,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30.0),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
// Connect with the user
|
||||
editBizProfileWindow(mzansiProfileProvider, width);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Edit Profile",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// Positioned(
|
||||
// right: 5,
|
||||
// bottom: 10,
|
||||
// child: MihFloatingMenu(
|
||||
// animatedIcon: AnimatedIcons.menu_close,
|
||||
// children: [
|
||||
// SpeedDialChild(
|
||||
// child: Icon(
|
||||
// Icons.edit,
|
||||
// color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
// label: "Edit Profile",
|
||||
// labelBackgroundColor:
|
||||
// MihColors.getGreenColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// labelStyle: TextStyle(
|
||||
// color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// backgroundColor:
|
||||
// MihColors.getGreenColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// onTap: () {
|
||||
// editBizProfileWindow(width);
|
||||
// },
|
||||
// )
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,790 @@
|
||||
import 'package:country_code_picker/country_code_picker.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_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_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_image_display.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_location_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_my_business_user_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihBusinessDetailsSetUp extends StatefulWidget {
|
||||
const MihBusinessDetailsSetUp({super.key});
|
||||
|
||||
@override
|
||||
State<MihBusinessDetailsSetUp> createState() =>
|
||||
_MihBusinessDetailsSetUpState();
|
||||
}
|
||||
|
||||
class _MihBusinessDetailsSetUpState extends State<MihBusinessDetailsSetUp> {
|
||||
final nameController = TextEditingController();
|
||||
final typeController = TextEditingController();
|
||||
final regController = TextEditingController();
|
||||
final addressController = TextEditingController();
|
||||
final fnameController = TextEditingController();
|
||||
final lnameController = TextEditingController();
|
||||
final titleController = TextEditingController();
|
||||
final signtureController = TextEditingController();
|
||||
final accessController = TextEditingController();
|
||||
final countryCodeController = TextEditingController();
|
||||
final contactController = TextEditingController();
|
||||
final emailController = TextEditingController();
|
||||
final locationController = TextEditingController();
|
||||
final practiceNoController = TextEditingController();
|
||||
final vatNoController = TextEditingController();
|
||||
final websiteController = TextEditingController();
|
||||
final ratingController = TextEditingController();
|
||||
final missionVisionController = TextEditingController();
|
||||
final logoFileNameController = TextEditingController();
|
||||
PlatformFile? newSelectedLogoPic;
|
||||
PlatformFile? newSelectedSignaturePic;
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
|
||||
final ValueNotifier<String> busType = ValueNotifier("");
|
||||
late String env;
|
||||
|
||||
void submitForm(MzansiProfileProvider mzansiProfileProvider) {
|
||||
if (isFieldsFilled()) {
|
||||
createBusinessProfileAPICall(mzansiProfileProvider);
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createBusinessProfileAPICall(
|
||||
MzansiProfileProvider mzansiProfileProvider) async {
|
||||
Response response =
|
||||
await MihBusinessDetailsServices().createBusinessDetails(
|
||||
mzansiProfileProvider,
|
||||
nameController.text,
|
||||
typeController.text,
|
||||
regController.text,
|
||||
practiceNoController.text,
|
||||
vatNoController.text,
|
||||
emailController.text,
|
||||
getNumberWithCountryCode(),
|
||||
locationController.text,
|
||||
logoFileNameController.text,
|
||||
websiteController.text,
|
||||
"0",
|
||||
missionVisionController.text,
|
||||
context,
|
||||
);
|
||||
if (response.statusCode == 201) {
|
||||
bool successUpload =
|
||||
await uploadFile(mzansiProfileProvider, newSelectedLogoPic);
|
||||
if (successUpload) {
|
||||
String logoUrl = await MihFileApi.getMinioFileUrl(
|
||||
mzansiProfileProvider.business!.logo_path);
|
||||
mzansiProfileProvider.setBusinessProfilePicUrl(logoUrl);
|
||||
}
|
||||
await createBusinessUserAPICall(mzansiProfileProvider);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createBusinessUserAPICall(
|
||||
MzansiProfileProvider mzansiProfileProvider) async {
|
||||
int statusCode = await MihMyBusinessUserServices().createBusinessUser(
|
||||
mzansiProfileProvider.business!.business_id,
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
signtureController.text,
|
||||
titleController.text,
|
||||
accessController.text,
|
||||
mzansiProfileProvider,
|
||||
context,
|
||||
);
|
||||
if (statusCode == 201) {
|
||||
bool successUpload =
|
||||
await uploadFile(mzansiProfileProvider, newSelectedSignaturePic);
|
||||
if (successUpload) {
|
||||
String sigUrl = await MihFileApi.getMinioFileUrl(
|
||||
mzansiProfileProvider.businessUser!.sig_path);
|
||||
mzansiProfileProvider.setBusinessUserSignatureUrl(sigUrl);
|
||||
String message =
|
||||
"Your business profile is now live! You can now start connecting with customers and growing your business.";
|
||||
successPopUp(message, false);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> uploadFile(
|
||||
MzansiProfileProvider mzansiProfileProvider, PlatformFile? image) async {
|
||||
if (newSelectedLogoPic != null) {
|
||||
int uploadStatusCode = 0;
|
||||
uploadStatusCode = await MihFileApi.uploadFile(
|
||||
mzansiProfileProvider.business!.business_id,
|
||||
env,
|
||||
"business_files",
|
||||
image,
|
||||
context,
|
||||
);
|
||||
if (uploadStatusCode == 200) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true; // No file selected, so no upload needed
|
||||
}
|
||||
}
|
||||
|
||||
bool isFieldsFilled() {
|
||||
if (typeController.text.isEmpty ||
|
||||
titleController.text.isEmpty ||
|
||||
accessController.text.isEmpty) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
String getNumberWithCountryCode() {
|
||||
String numberWithoutBeginingZero = "";
|
||||
if (contactController.text[0] == "0") {
|
||||
numberWithoutBeginingZero = contactController.text
|
||||
.replaceAll(" ", "")
|
||||
.substring(1, contactController.text.length);
|
||||
} else {
|
||||
numberWithoutBeginingZero = contactController.text.replaceAll("-", " ");
|
||||
}
|
||||
return "${countryCodeController.text}-$numberWithoutBeginingZero";
|
||||
}
|
||||
|
||||
Color getMissionVisionLimitColor(int limit) {
|
||||
if (_counter.value <= limit) {
|
||||
return MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
} else {
|
||||
return MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
}
|
||||
}
|
||||
|
||||
void typeSelected() {
|
||||
if (typeController.text.isNotEmpty) {
|
||||
busType.value = typeController.text;
|
||||
} else {
|
||||
busType.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
void successPopUp(String message, bool stayOnPersonalSide) {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
"Successfully Updated Profile",
|
||||
message,
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
extra: stayOnPersonalSide,
|
||||
);
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
void initialiseControlers(MzansiProfileProvider mzansiProfileProvider) {
|
||||
typeController.addListener(typeSelected);
|
||||
setState(() {
|
||||
fnameController.text = mzansiProfileProvider.user!.fname;
|
||||
lnameController.text = mzansiProfileProvider.user!.lname;
|
||||
accessController.text = "Full";
|
||||
countryCodeController.text = "+27";
|
||||
});
|
||||
if (AppEnviroment.getEnv() == "Prod") {
|
||||
env = "Prod";
|
||||
} else {
|
||||
env = "Dev";
|
||||
}
|
||||
missionVisionController.addListener(() {
|
||||
setState(() {
|
||||
_counter.value = missionVisionController.text.characters.length;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
typeController.removeListener(typeSelected);
|
||||
nameController.dispose();
|
||||
typeController.dispose();
|
||||
regController.dispose();
|
||||
addressController.dispose();
|
||||
fnameController.dispose();
|
||||
lnameController.dispose();
|
||||
titleController.dispose();
|
||||
signtureController.dispose();
|
||||
accessController.dispose();
|
||||
countryCodeController.dispose();
|
||||
contactController.dispose();
|
||||
emailController.dispose();
|
||||
locationController.dispose();
|
||||
practiceNoController.dispose();
|
||||
vatNoController.dispose();
|
||||
websiteController.dispose();
|
||||
ratingController.dispose();
|
||||
missionVisionController.dispose();
|
||||
logoFileNameController.dispose();
|
||||
busType.dispose();
|
||||
_focusNode.dispose();
|
||||
_counter.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initialiseControlers(context.read<MzansiProfileProvider>());
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(screenWidth),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return KeyboardListener(
|
||||
focusNode: _focusNode,
|
||||
autofocus: true,
|
||||
onKeyEvent: (event) async {
|
||||
if (event is KeyDownEvent &&
|
||||
event.logicalKey == LogicalKeyboardKey.enter) {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitForm(mzansiProfileProvider);
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.2)
|
||||
: EdgeInsets.symmetric(horizontal: width * 0.075),
|
||||
child: Column(
|
||||
children: [
|
||||
const Text(
|
||||
"Business Details",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 25,
|
||||
),
|
||||
),
|
||||
Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark")),
|
||||
const SizedBox(height: 10.0),
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
Center(
|
||||
child: MihCircleAvatar(
|
||||
imageFile: newSelectedLogoPic != null
|
||||
? MemoryImage(newSelectedLogoPic!.bytes!)
|
||||
: mzansiProfileProvider.businessProfilePicture,
|
||||
width: 150,
|
||||
editable: true,
|
||||
fileNameController: logoFileNameController,
|
||||
userSelectedfile: newSelectedLogoPic,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onChange: (selectedfile) {
|
||||
setState(() {
|
||||
newSelectedLogoPic = selectedfile;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: nameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Business Name",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: typeController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Business Type",
|
||||
validator: (value) {
|
||||
return MihValidationServices()
|
||||
.validateNoSpecialChars(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: emailController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Business Email",
|
||||
validator: (value) {
|
||||
return MihValidationServices().validateEmail(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
Container(
|
||||
width: 300,
|
||||
alignment: Alignment.topLeft,
|
||||
child: const Text(
|
||||
"Contact Number:",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
CountryCodePicker(
|
||||
padding: EdgeInsetsGeometry.all(0),
|
||||
onChanged: (selectedCode) {
|
||||
setState(() {
|
||||
countryCodeController.text =
|
||||
selectedCode.toString();
|
||||
});
|
||||
debugPrint(
|
||||
"Selected Country Code: ${countryCodeController.text}");
|
||||
},
|
||||
initialSelection: countryCodeController.text,
|
||||
showDropDownButton: false,
|
||||
pickerStyle: PickerStyle.bottomSheet,
|
||||
dialogBackgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
barrierColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
Expanded(
|
||||
child: MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: contactController,
|
||||
numberMode: true,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: null,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
height: 250,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: missionVisionController,
|
||||
multiLineInput: true,
|
||||
requiredText: true,
|
||||
hintText: "Business Mission & Vision",
|
||||
validator: (value) {
|
||||
return MihValidationServices().validateLength(
|
||||
missionVisionController.text, 256);
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
height: 15,
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: _counter,
|
||||
builder:
|
||||
(BuildContext context, int value, Widget? child) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
"$value",
|
||||
style: TextStyle(
|
||||
color: getMissionVisionLimitColor(256),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
"/256",
|
||||
style: TextStyle(
|
||||
color: getMissionVisionLimitColor(256),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: websiteController,
|
||||
multiLineInput: false,
|
||||
requiredText: false,
|
||||
hintText: "Business Website",
|
||||
validator: (value) {
|
||||
return MihValidationServices()
|
||||
.validateWebsite(value, false);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: regController,
|
||||
multiLineInput: false,
|
||||
requiredText: false,
|
||||
hintText: "Registration No.",
|
||||
validator: (value) {
|
||||
// return MihValidationServices().isEmpty(value);
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: practiceNoController,
|
||||
multiLineInput: false,
|
||||
requiredText: false,
|
||||
hintText: "Practice Number",
|
||||
validator: (validateValue) {
|
||||
return null;
|
||||
},
|
||||
),
|
||||
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: vatNoController,
|
||||
multiLineInput: false,
|
||||
requiredText: false,
|
||||
hintText: "VAT Number",
|
||||
validator: (value) {
|
||||
// return MihValidationServices().isEmpty(value);
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Flexible(
|
||||
child: MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: locationController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "GPS Location",
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10.0),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return const Mihloadingcircle(
|
||||
message: "Getting your location",
|
||||
);
|
||||
},
|
||||
);
|
||||
MIHLocationAPI()
|
||||
.getGPSPosition(context)
|
||||
.then((position) {
|
||||
if (position != null) {
|
||||
setState(() {
|
||||
locationController.text =
|
||||
"${position.latitude}, ${position.longitude}";
|
||||
});
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
});
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 100,
|
||||
child: Text(
|
||||
"Set",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 15.0),
|
||||
//const SizedBox(height: 15.0),
|
||||
const Center(
|
||||
child: Text(
|
||||
"Business User",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 22,
|
||||
),
|
||||
),
|
||||
),
|
||||
Divider(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark")),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: titleController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Title",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
// MihDropdownField(
|
||||
// controller: titleController,
|
||||
// hintText: "Title",
|
||||
// dropdownOptions: const ["Doctor", "Assistant", "Other"],
|
||||
// editable: true,
|
||||
// enableSearch: true,
|
||||
// validator: (value) {
|
||||
// return MihValidationServices().isEmpty(value);
|
||||
// },
|
||||
// requiredText: true,
|
||||
// ),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: fnameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "First Name",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: lnameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Surname",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: accessController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Access Type",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
width: 300,
|
||||
alignment: Alignment.topLeft,
|
||||
child: const Text(
|
||||
"Signature:",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: MihImageDisplay(
|
||||
imageFile: newSelectedSignaturePic != null
|
||||
? MemoryImage(newSelectedSignaturePic!.bytes!)
|
||||
: mzansiProfileProvider.businessUserSignature,
|
||||
width: 300,
|
||||
height: 200,
|
||||
editable: true,
|
||||
fileNameController: signtureController,
|
||||
userSelectedfile: newSelectedSignaturePic,
|
||||
onChange: (selectedFile) {
|
||||
setState(() {
|
||||
newSelectedSignaturePic = selectedFile;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20.0),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitForm(mzansiProfileProvider);
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Add",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
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/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.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_package_components/mih_business_info_card.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihBusinessDetailsView extends StatefulWidget {
|
||||
const MihBusinessDetailsView({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihBusinessDetailsView> createState() => _MihBusinessDetailsViewState();
|
||||
}
|
||||
|
||||
class _MihBusinessDetailsViewState extends State<MihBusinessDetailsView> {
|
||||
late Future<String> futureImageUrl;
|
||||
PlatformFile? file;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
MzansiDirectoryProvider directoryProvider =
|
||||
context.read<MzansiDirectoryProvider>();
|
||||
futureImageUrl = MihFileApi.getMinioFileUrl(
|
||||
directoryProvider.selectedBusiness!.logo_path);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(screenWidth, context),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width, BuildContext context) {
|
||||
double profilePictureWidth = 150;
|
||||
return Consumer<MzansiDirectoryProvider>(
|
||||
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
|
||||
Widget? child) {
|
||||
return Stack(
|
||||
children: [
|
||||
MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding: MzansiInnovationHub.of(context)!.theme.screenType ==
|
||||
"desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.2)
|
||||
: EdgeInsets.symmetric(horizontal: width * 0.075),
|
||||
child: Column(
|
||||
children: [
|
||||
FutureBuilder(
|
||||
future: futureImageUrl,
|
||||
builder: (context, asyncSnapshot) {
|
||||
if (asyncSnapshot.connectionState ==
|
||||
ConnectionState.done &&
|
||||
asyncSnapshot.hasData) {
|
||||
if (asyncSnapshot.requireData != "") {
|
||||
return MihCircleAvatar(
|
||||
imageFile: CachedNetworkImageProvider(
|
||||
asyncSnapshot.requireData),
|
||||
width: profilePictureWidth,
|
||||
editable: false,
|
||||
fileNameController: TextEditingController(),
|
||||
userSelectedfile: file,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
onChange: () {},
|
||||
);
|
||||
} else {
|
||||
return Icon(
|
||||
MihIcons.iDontKnow,
|
||||
size: profilePictureWidth,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return Icon(
|
||||
MihIcons.mihRing,
|
||||
size: profilePictureWidth,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
);
|
||||
}
|
||||
}),
|
||||
// Center(
|
||||
// child: MihCircleAvatar(
|
||||
// imageFile: widget.logoImage,
|
||||
// width: 150,
|
||||
// editable: false,
|
||||
// fileNameController: fileNameController,
|
||||
// userSelectedfile: imageFile,
|
||||
// frameColor:
|
||||
// MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// backgroundColor:
|
||||
// MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// onChange: (selectedfile) {
|
||||
// setState(() {
|
||||
// imageFile = selectedfile;
|
||||
// });
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
directoryProvider.selectedBusiness!.Name,
|
||||
style: TextStyle(
|
||||
fontSize: 35,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
directoryProvider.selectedBusiness!.type,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
// FittedBox(
|
||||
// child: Text(
|
||||
// "Mission & Vision",
|
||||
// style: TextStyle(
|
||||
// fontSize: 15,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// color: MzansiInnovationHub.of(context)!
|
||||
// .theme
|
||||
// .secondaryColor(),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
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.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
RatingBar.readOnly(
|
||||
size: 50,
|
||||
alignment: Alignment.center,
|
||||
filledIcon: Icons.star,
|
||||
emptyIcon: Icons.star_border,
|
||||
halfFilledIcon: Icons.star_half,
|
||||
filledColor: MihColors.getYellowColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
// MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
emptyColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
halfFilledColor: MihColors.getYellowColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
// MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
isHalfAllowed: true,
|
||||
initialRating:
|
||||
directoryProvider.selectedBusiness!.rating.isNotEmpty
|
||||
? double.parse(
|
||||
directoryProvider.selectedBusiness!.rating)
|
||||
: 0,
|
||||
maxRating: 5,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(
|
||||
width: 700,
|
||||
child: MihBusinessCard(
|
||||
business: directoryProvider.selectedBusiness!,
|
||||
width: width,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,440 @@
|
||||
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:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/business.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_floating_menu.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_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';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.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 MihBusinessQrCode extends StatefulWidget {
|
||||
final Business? business;
|
||||
const MihBusinessQrCode({
|
||||
super.key,
|
||||
required this.business,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihBusinessQrCode> createState() => _MihBusinessQrCodeState();
|
||||
}
|
||||
|
||||
class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
|
||||
late Future<String> futureImageUrl;
|
||||
late Business business;
|
||||
PlatformFile? file;
|
||||
late String qrCodedata;
|
||||
int qrSize = 500;
|
||||
bool _isUserSignedIn = false;
|
||||
ScreenshotController screenshotController = ScreenshotController();
|
||||
Uint8List? businessQRImageFile;
|
||||
|
||||
Future<void> _checkUserSession() async {
|
||||
final doesSessionExist = await SuperTokens.doesSessionExist();
|
||||
setState(() {
|
||||
_isUserSignedIn = doesSessionExist;
|
||||
});
|
||||
}
|
||||
|
||||
String getQrCodeData(int qrSize) {
|
||||
String color = MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
|
||||
.toARGB32()
|
||||
.toRadixString(16)
|
||||
.substring(2, 8);
|
||||
// KenLogger.warning(color);
|
||||
String bgColor = MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
|
||||
.toARGB32()
|
||||
.toRadixString(16)
|
||||
.substring(2, 8);
|
||||
// KenLogger.warning(bgColor);
|
||||
String encodedData =
|
||||
Uri.encodeComponent("$qrCodedata${business.business_id}");
|
||||
|
||||
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 =
|
||||
"${business.Name}_QR_Code_${DateTime.now().millisecondsSinceEpoch}.png";
|
||||
if (kIsWeb) {
|
||||
await FileSaver.instance.saveFile(
|
||||
name: filename,
|
||||
bytes: imageBytes,
|
||||
fileExtension: "png",
|
||||
mimeType: MimeType.png,
|
||||
);
|
||||
} 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(() {
|
||||
businessQRImageFile = image;
|
||||
});
|
||||
}).catchError((onError) {
|
||||
KenLogger.error(onError);
|
||||
});
|
||||
KenLogger.success("QR Code Image Captured : $businessQRImageFile");
|
||||
saveImage(businessQRImageFile!);
|
||||
} 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.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
Text(
|
||||
"Let's Get Started",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget displayBusinessQRCode(double profilePictureWidth) {
|
||||
return Screenshot(
|
||||
controller: screenshotController,
|
||||
child: Material(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
|
||||
.withValues(alpha: 0.6),
|
||||
borderRadius: BorderRadius.circular(25),
|
||||
elevation: 10,
|
||||
shadowColor: Colors.black,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
FutureBuilder(
|
||||
future: futureImageUrl,
|
||||
builder: (context, asyncSnapshot) {
|
||||
if (asyncSnapshot.connectionState ==
|
||||
ConnectionState.done &&
|
||||
asyncSnapshot.hasData) {
|
||||
if (asyncSnapshot.requireData != "" ||
|
||||
asyncSnapshot.requireData.isNotEmpty) {
|
||||
return MihCircleAvatar(
|
||||
imageFile: CachedNetworkImageProvider(
|
||||
asyncSnapshot.requireData),
|
||||
width: profilePictureWidth,
|
||||
editable: false,
|
||||
fileNameController: TextEditingController(),
|
||||
userSelectedfile: file,
|
||||
frameColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
backgroundColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onChange: () {},
|
||||
);
|
||||
} else {
|
||||
return Icon(
|
||||
MihIcons.iDontKnow,
|
||||
size: profilePictureWidth,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return Icon(
|
||||
MihIcons.mihRing,
|
||||
size: profilePictureWidth,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
business.Name,
|
||||
style: TextStyle(
|
||||
fontSize: 35,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
business.type,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
FittedBox(
|
||||
child: Text(
|
||||
"Powered by MIH",
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Icon(
|
||||
MihIcons.mihLogo,
|
||||
size: 20,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
SizedBox(
|
||||
width: 300,
|
||||
height: 300,
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: getQrCodeData(qrSize.toInt()),
|
||||
placeholder: (context, url) => const Mihloadingcircle(),
|
||||
errorWidget: (context, url, error) =>
|
||||
const Icon(Icons.error),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
"Scan & Connect",
|
||||
style: TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void shareMIHLink(BuildContext context, String message, String link) {
|
||||
String shareText = "$message: $link";
|
||||
SharePlus.instance.share(
|
||||
ShareParams(text: shareText),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
MzansiProfileProvider profileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
if (widget.business != null) {
|
||||
business = widget.business!;
|
||||
} else {
|
||||
business = profileProvider.business!;
|
||||
}
|
||||
_checkUserSession();
|
||||
futureImageUrl = MihFileApi.getMinioFileUrl(business.logo_path);
|
||||
qrCodedata =
|
||||
"${AppEnviroment.baseAppUrl}/business-profile/view?business_id=";
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Size screenSize = MediaQuery.of(context).size;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(screenSize, context),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(Size screenSize, BuildContext context) {
|
||||
double profilePictureWidth = 150;
|
||||
return Stack(
|
||||
alignment: Alignment.topCenter,
|
||||
children: [
|
||||
MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15.0),
|
||||
child: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: screenSize.width * 0.2)
|
||||
: EdgeInsets.symmetric(
|
||||
horizontal: screenSize.width * 0), //.075),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 10.0),
|
||||
child: displayBusinessQRCode(profilePictureWidth),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 10,
|
||||
bottom: 10,
|
||||
child: MihFloatingMenu(
|
||||
animatedIcon: AnimatedIcons.menu_close,
|
||||
children: [
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.download_rounded,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Download QR Code",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
downloadQrCode();
|
||||
},
|
||||
),
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.share_rounded,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Share Business",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
shareMIHLink(
|
||||
context,
|
||||
"Check out ${business.Name} on the MIH app's Mzansi Directory",
|
||||
"$qrCodedata${business.business_id}",
|
||||
);
|
||||
},
|
||||
),
|
||||
]),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
import 'package:custom_rating_bar/custom_rating_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/main.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_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_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_review_business_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihBusinessReviews extends StatefulWidget {
|
||||
final Business? business;
|
||||
const MihBusinessReviews({
|
||||
super.key,
|
||||
required this.business,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihBusinessReviews> createState() => _MihBusinessReviewsState();
|
||||
}
|
||||
|
||||
class _MihBusinessReviewsState extends State<MihBusinessReviews> {
|
||||
late Business business;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
MzansiProfileProvider profileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
if (widget.business != null) {
|
||||
business = widget.business!;
|
||||
} else {
|
||||
business = profileProvider.business!;
|
||||
}
|
||||
}
|
||||
|
||||
void onReviewTap(BusinessReview? businessReview, double width) {
|
||||
// showDialog(context: context, builder: (context)=> )
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return MihReviewBusinessWindow(
|
||||
business: business,
|
||||
businessReview: businessReview,
|
||||
screenWidth: width,
|
||||
readOnly: true,
|
||||
onSuccessDismissPressed: () {},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return FutureBuilder(
|
||||
future: MihMzansiDirectoryServices().getAllReviewsofBusiness(
|
||||
business.business_id,
|
||||
),
|
||||
builder: (context, asyncSnapshot) {
|
||||
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Mihloadingcircle();
|
||||
} else if (asyncSnapshot.connectionState == ConnectionState.done &&
|
||||
asyncSnapshot.hasData) {
|
||||
List<BusinessReview> reviews = asyncSnapshot.data!;
|
||||
print("Reviews: ${reviews.length}");
|
||||
if (reviews.isEmpty) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Stack(
|
||||
alignment: AlignmentDirectional.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 10.0),
|
||||
child: Icon(
|
||||
MihIcons.mihRing,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.star_rate_rounded,
|
||||
size: 150,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"No reviews yet, be the first the review ${business.Name}",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
// const SizedBox(height: 10),
|
||||
// Center(
|
||||
// child: RichText(
|
||||
// textAlign: TextAlign.center,
|
||||
// text: TextSpan(
|
||||
// style: TextStyle(
|
||||
// fontSize: 20,
|
||||
// fontWeight: FontWeight.normal,
|
||||
// color: MzansiInnovationHub.of(context)!
|
||||
// .theme
|
||||
// .secondaryColor(),
|
||||
// ),
|
||||
// children: [
|
||||
// TextSpan(text: "Press "),
|
||||
// WidgetSpan(
|
||||
// alignment: PlaceholderAlignment.middle,
|
||||
// child: Icon(
|
||||
// Icons.menu,
|
||||
// size: 20,
|
||||
// color: MzansiInnovationHub.of(context)!
|
||||
// .theme
|
||||
// .secondaryColor(),
|
||||
// ),
|
||||
// ),
|
||||
// TextSpan(text: " to add your first loyalty card"),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
// return Column(
|
||||
// children: [
|
||||
// const SizedBox(height: 50),
|
||||
// Icon(
|
||||
// Icons.star_rate_rounded,
|
||||
// size: 150,
|
||||
// color:
|
||||
// MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// ),
|
||||
// Text(
|
||||
// "No reviews yet, be the first the review\n${widget.business.Name}",
|
||||
// textAlign: TextAlign.center,
|
||||
// style: TextStyle(
|
||||
// fontSize: 18,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
} else {
|
||||
int descriptionDisplayCOunt = 75;
|
||||
return ListView.separated(
|
||||
itemCount: reviews.length,
|
||||
separatorBuilder: (context, index) => Divider(),
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
onReviewTap(reviews[index], screenWidth);
|
||||
},
|
||||
title: RatingBar.readOnly(
|
||||
size: 25,
|
||||
alignment: Alignment.centerLeft,
|
||||
filledIcon: Icons.star,
|
||||
emptyIcon: Icons.star_border,
|
||||
halfFilledIcon: Icons.star_half,
|
||||
filledColor: MihColors.getYellowColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
// MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
emptyColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
halfFilledColor: MihColors.getYellowColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
// MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// filledColor:
|
||||
// MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// emptyColor:
|
||||
// MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// halfFilledColor:
|
||||
// MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
isHalfAllowed: true,
|
||||
initialRating: double.parse(reviews[index].rating_score),
|
||||
maxRating: 5,
|
||||
),
|
||||
subtitle: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
// Text(
|
||||
// "${reviews[index].reviewer} ",
|
||||
// style: TextStyle(
|
||||
// fontSize: 15,
|
||||
// fontWeight: FontWeight.bold,
|
||||
// ),
|
||||
// ),
|
||||
Text(
|
||||
reviews[index].rating_title,
|
||||
softWrap: true,
|
||||
textAlign: TextAlign.left,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: reviews[index].rating_description.isNotEmpty,
|
||||
child: Text(
|
||||
reviews[index].rating_description.isEmpty
|
||||
? ""
|
||||
: "${reviews[index].rating_description.substring(0, reviews[index].rating_description.length >= descriptionDisplayCOunt ? descriptionDisplayCOunt : reviews[index].rating_description.length - 1)}${reviews[index].rating_description.length >= descriptionDisplayCOunt ? "..." : ""}",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${reviews[index].date_time.split("T")[0]} ",
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return Center(child: Text('Error'));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_search_bar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/app_user.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/builders/build_user_list.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihBusinessUserSearch extends StatefulWidget {
|
||||
const MihBusinessUserSearch({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihBusinessUserSearch> createState() => _MihBusinessUserSearchState();
|
||||
}
|
||||
|
||||
class _MihBusinessUserSearchState extends State<MihBusinessUserSearch> {
|
||||
final TextEditingController searchController = TextEditingController();
|
||||
late Future<List<AppUser>> userSearchResults;
|
||||
final FocusNode _searchFocusNode = FocusNode();
|
||||
bool hasSearchedBefore = false;
|
||||
String userSearch = "";
|
||||
String errorCode = "";
|
||||
String errorBody = "";
|
||||
|
||||
Future<List<AppUser>> fetchUsers(
|
||||
MzansiProfileProvider profileProvider, String search) async {
|
||||
return MihUserServices().searchUsers(profileProvider, search, context);
|
||||
}
|
||||
|
||||
void submitUserForm(MzansiProfileProvider profileProvider) {
|
||||
if (searchController.text != "") {
|
||||
userSearch = searchController.text;
|
||||
hasSearchedBefore = true;
|
||||
userSearchResults = fetchUsers(profileProvider, userSearch);
|
||||
}
|
||||
}
|
||||
|
||||
Widget displayUserList(MzansiProfileProvider profileProvider) {
|
||||
if (profileProvider.userSearchResults.isNotEmpty) {
|
||||
return Expanded(child: BuildUserList());
|
||||
}
|
||||
if (hasSearchedBefore && userSearch.isNotEmpty) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.iDontKnow,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Let's try refining your search",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.personalProfile,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Search for a member of Mzansi to add to your team",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "You can search using their username or email"),
|
||||
// WidgetSpan(
|
||||
// alignment: PlaceholderAlignment.middle,
|
||||
// child: Icon(
|
||||
// Icons.menu,
|
||||
// size: 20,
|
||||
// color: MzansiInnovationHub.of(context)!
|
||||
// .theme
|
||||
// .secondaryColor(),
|
||||
// ),
|
||||
// ),
|
||||
// TextSpan(text: " to add your first loyalty card"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
// return Center(
|
||||
// child: Text(
|
||||
// "Enter Username or Email to search",
|
||||
// style: TextStyle(
|
||||
// fontSize: 25,
|
||||
// color: MihColors.getGreyColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
|
||||
// textAlign: TextAlign.center,
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TODO: implement dispose
|
||||
super.dispose();
|
||||
_searchFocusNode.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
final double width = size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(width),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
// dscvds
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
Widget? child) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: MihSearchBar(
|
||||
controller: searchController,
|
||||
hintText: "Search Users",
|
||||
prefixIcon: Icons.search,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
hintColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onPrefixIconTap: () {
|
||||
submitUserForm(profileProvider);
|
||||
},
|
||||
onClearIconTap: () {
|
||||
setState(() {
|
||||
searchController.clear();
|
||||
userSearch = "";
|
||||
});
|
||||
profileProvider.setUserearchResults(userSearchResults: []);
|
||||
},
|
||||
searchFocusNode: _searchFocusNode,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
displayUserList(profileProvider),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/business_employee.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/builders/build_employee_list.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihMyBusinessTeam extends StatefulWidget {
|
||||
const MihMyBusinessTeam({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihMyBusinessTeam> createState() => _MihMyBusinessTeamState();
|
||||
}
|
||||
|
||||
class _MihMyBusinessTeamState extends State<MihMyBusinessTeam> {
|
||||
String errorCode = "";
|
||||
String errorBody = "";
|
||||
|
||||
// void getEmployeeData(MzansiProfileProvider mzansiProfileProvider) {
|
||||
// WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
// await MihBusinessEmployeeServices()
|
||||
// .fetchEmployees(mzansiProfileProvider, context);
|
||||
// });
|
||||
// }
|
||||
|
||||
Widget displayEmployeeList(List<BusinessEmployee> employeeList) {
|
||||
if (employeeList.isNotEmpty) {
|
||||
return Expanded(child: BuildEmployeeList());
|
||||
}
|
||||
return Center(
|
||||
child: Text(
|
||||
"",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
color: MihColors.getGreyColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// fetchEmployees(context.read<MzansiProfileProvider>()).catchError((e) {
|
||||
// // Handle the error thrown in fetchEmployees
|
||||
// print('Error fetching employees: $e');
|
||||
// });
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody() {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
if (mzansiProfileProvider.employeeList == null) {
|
||||
return Center(
|
||||
child: Mihloadingcircle(),
|
||||
);
|
||||
}
|
||||
return Column(
|
||||
children: [
|
||||
displayEmployeeList(mzansiProfileProvider.employeeList!),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
import 'dart:ui';
|
||||
|
||||
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_package_components/mih_circle_avatar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_image_display.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_update_my_business_user_details.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihMyBusinessUser extends StatefulWidget {
|
||||
const MihMyBusinessUser({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihMyBusinessUser> createState() => _MihMyBusinessUserState();
|
||||
}
|
||||
|
||||
class _MihMyBusinessUserState extends State<MihMyBusinessUser> {
|
||||
final fileNameController = TextEditingController();
|
||||
final signtureController = TextEditingController();
|
||||
PlatformFile? userPicFile;
|
||||
PlatformFile? newSelectedSignaturePic;
|
||||
|
||||
void editBizUserProfileWindow(
|
||||
MzansiProfileProvider mzansiProfileProvider, double width) {
|
||||
showDialog(
|
||||
barrierDismissible: false,
|
||||
context: context,
|
||||
builder: (context) => MihUpdateMyBusinessUserDetails(),
|
||||
);
|
||||
}
|
||||
|
||||
String getDisplayText(
|
||||
MzansiProfileProvider profileProvider, String originalText) {
|
||||
int textLength = originalText.length >= 13 ? 13 : 6;
|
||||
String displayText = "";
|
||||
if (profileProvider.hideBusinessUserDetails) {
|
||||
for (int i = 0; i < textLength; i++) {
|
||||
displayText += "●";
|
||||
}
|
||||
} else {
|
||||
displayText = originalText;
|
||||
}
|
||||
return displayText;
|
||||
}
|
||||
|
||||
Widget buildEmployeeInfoCard(MzansiProfileProvider profileProvider) {
|
||||
TextStyle titleStyle = TextStyle(
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
TextStyle subtitleStyle = TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
TextStyle subtitleHeadingStyle = TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Employee Info Card",
|
||||
onWindowTapClose: null,
|
||||
backgroundColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
foregroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
windowBody: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${profileProvider.user!.fname} ${profileProvider.user!.lname}",
|
||||
style: titleStyle,
|
||||
),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "Title: ",
|
||||
style: subtitleHeadingStyle,
|
||||
),
|
||||
TextSpan(
|
||||
text: profileProvider.businessUser!.title,
|
||||
style: subtitleStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: "Access: ",
|
||||
style: subtitleHeadingStyle,
|
||||
),
|
||||
TextSpan(
|
||||
text: getDisplayText(profileProvider,
|
||||
profileProvider.businessUser!.access),
|
||||
style: subtitleStyle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void setControllers() {
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
fileNameController.text =
|
||||
mzansiProfileProvider.user!.pro_pic_path.split("/").last;
|
||||
signtureController.text =
|
||||
mzansiProfileProvider.businessUser!.sig_path.split("/").last;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
fileNameController.dispose();
|
||||
signtureController.dispose();
|
||||
userPicFile = null;
|
||||
newSelectedSignaturePic = null;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
setControllers();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(screenWidth),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return Stack(
|
||||
children: [
|
||||
MihSingleChildScroll(
|
||||
child: Padding(
|
||||
padding: MzansiInnovationHub.of(context)!.theme.screenType ==
|
||||
"desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.2)
|
||||
: EdgeInsets.symmetric(horizontal: width * 0.075),
|
||||
child: Column(
|
||||
children: [
|
||||
Center(
|
||||
child: MihCircleAvatar(
|
||||
imageFile: mzansiProfileProvider.userProfilePicture,
|
||||
width: 150,
|
||||
editable: false,
|
||||
fileNameController: fileNameController,
|
||||
userSelectedfile: userPicFile,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onChange: (_) {},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
buildEmployeeInfoCard(mzansiProfileProvider),
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
width: 300,
|
||||
alignment: Alignment.topLeft,
|
||||
child: const Text(
|
||||
"Signature:",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: mzansiProfileProvider.hideBusinessUserDetails
|
||||
? ClipRRect(
|
||||
borderRadius: BorderRadius.circular(300 * 0.1),
|
||||
child: ImageFiltered(
|
||||
imageFilter: ImageFilter.blur(
|
||||
sigmaX: 15.0, sigmaY: 15.0),
|
||||
child: MihImageDisplay(
|
||||
key: UniqueKey(),
|
||||
imageFile: mzansiProfileProvider
|
||||
.businessUserSignature,
|
||||
width: 300,
|
||||
height: 200,
|
||||
editable: false,
|
||||
fileNameController: signtureController,
|
||||
userSelectedfile: newSelectedSignaturePic,
|
||||
onChange: (selectedFile) {},
|
||||
),
|
||||
),
|
||||
)
|
||||
: MihImageDisplay(
|
||||
key: UniqueKey(),
|
||||
imageFile:
|
||||
mzansiProfileProvider.businessUserSignature,
|
||||
width: 300,
|
||||
height: 200,
|
||||
editable: false,
|
||||
fileNameController: signtureController,
|
||||
userSelectedfile: newSelectedSignaturePic,
|
||||
onChange: (selectedFile) {},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
editBizUserProfileWindow(
|
||||
mzansiProfileProvider, width);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Edit Profile",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 5,
|
||||
top: 5,
|
||||
child: MihButton(
|
||||
width: 40,
|
||||
height: 40,
|
||||
onPressed: () {
|
||||
mzansiProfileProvider.setHideBusinessUserDetails(
|
||||
!mzansiProfileProvider.hideBusinessUserDetails);
|
||||
},
|
||||
buttonColor: mzansiProfileProvider.hideBusinessUserDetails
|
||||
? MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
|
||||
: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
child: Icon(
|
||||
mzansiProfileProvider.hideBusinessUserDetails
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,528 @@
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_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_form.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_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_toggle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihEditPersonalProfileWindow extends StatefulWidget {
|
||||
const MihEditPersonalProfileWindow({super.key});
|
||||
|
||||
@override
|
||||
State<MihEditPersonalProfileWindow> createState() =>
|
||||
_MihEditPersonalProfileWindowState();
|
||||
}
|
||||
|
||||
class _MihEditPersonalProfileWindowState
|
||||
extends State<MihEditPersonalProfileWindow> {
|
||||
TextEditingController proPicController = TextEditingController();
|
||||
TextEditingController usernameController = TextEditingController();
|
||||
TextEditingController fnameController = TextEditingController();
|
||||
TextEditingController lnameController = TextEditingController();
|
||||
TextEditingController purposeController = TextEditingController();
|
||||
bool _controllersInitialized = false;
|
||||
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
PlatformFile? newSelectedProPic;
|
||||
String oldProPicName = "";
|
||||
String env = "";
|
||||
bool businessUser = false;
|
||||
|
||||
void initializeControllers(MzansiProfileProvider mzansiProfileProvider) {
|
||||
businessUser = mzansiProfileProvider.user!.type == "business";
|
||||
oldProPicName = mzansiProfileProvider.user!.pro_pic_path.isNotEmpty
|
||||
? mzansiProfileProvider.user!.pro_pic_path.split("/").last
|
||||
: "";
|
||||
env = AppEnviroment.getEnv() == "Prod" ? env = "Prod" : env = "Dev";
|
||||
if (!_controllersInitialized && mzansiProfileProvider.user != null) {
|
||||
usernameController.text = mzansiProfileProvider.user!.username;
|
||||
fnameController.text = mzansiProfileProvider.user!.fname;
|
||||
lnameController.text = mzansiProfileProvider.user!.lname;
|
||||
purposeController.text = mzansiProfileProvider.user!.purpose;
|
||||
proPicController.text =
|
||||
mzansiProfileProvider.user!.pro_pic_path.isNotEmpty
|
||||
? mzansiProfileProvider.user!.pro_pic_path.split("/").last
|
||||
: "";
|
||||
businessUser = mzansiProfileProvider.user!.type == "business";
|
||||
_controllersInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> submitForm(MzansiProfileProvider mzansiProfileProvider) async {
|
||||
if (mzansiProfileProvider.user!.username != usernameController.text) {
|
||||
bool isUsernameUnique = await MihUserServices.isUsernameUnique(
|
||||
usernameController.text, context);
|
||||
if (isUsernameUnique == false) {
|
||||
notUniqueAlert();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (oldProPicName != proPicController.text) {
|
||||
await uploadSelectedFile(mzansiProfileProvider, newSelectedProPic);
|
||||
}
|
||||
await updateUserApiCall(mzansiProfileProvider);
|
||||
}
|
||||
|
||||
Future<void> updateUserApiCall(
|
||||
MzansiProfileProvider mzansiProfileProvider) async {
|
||||
KenLogger.success("businessUser: $businessUser");
|
||||
int responseCode = await MihUserServices().updateUserV2(
|
||||
mzansiProfileProvider.user!,
|
||||
fnameController.text,
|
||||
lnameController.text,
|
||||
usernameController.text,
|
||||
proPicController.text,
|
||||
purposeController.text,
|
||||
businessUser,
|
||||
context,
|
||||
);
|
||||
if (responseCode == 200) {
|
||||
setState(() {
|
||||
setProfileVariables(mzansiProfileProvider);
|
||||
newSelectedProPic = null;
|
||||
});
|
||||
// if (originalProfileTypeIsBusiness == false && businessUser == true) {
|
||||
// stayOnPersonalSide = false;
|
||||
// }
|
||||
String message = "Your information has been updated successfully!";
|
||||
successPopUp(
|
||||
mzansiProfileProvider,
|
||||
message,
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> uploadSelectedFile(
|
||||
MzansiProfileProvider mzansiProfileProvider, PlatformFile? file) async {
|
||||
var response = await MihFileApi.uploadFile(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
env,
|
||||
"profile_files",
|
||||
file,
|
||||
context,
|
||||
);
|
||||
if (response == 200) {
|
||||
deleteFileApiCall(mzansiProfileProvider, oldProPicName);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteFileApiCall(
|
||||
MzansiProfileProvider mzansiProfileProvider, String filename) async {
|
||||
var response = await MihFileApi.deleteFile(
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
env,
|
||||
"profile_files",
|
||||
filename,
|
||||
context,
|
||||
);
|
||||
if (response == 200) {
|
||||
//SQL delete
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
|
||||
void setProfileVariables(MzansiProfileProvider mzansiProfileProvider) {
|
||||
businessUser = mzansiProfileProvider.user!.type == "business";
|
||||
oldProPicName = mzansiProfileProvider.user!.pro_pic_path.isNotEmpty
|
||||
? mzansiProfileProvider.user!.pro_pic_path.split("/").last
|
||||
: "";
|
||||
env = AppEnviroment.getEnv() == "Prod" ? env = "Prod" : env = "Dev";
|
||||
}
|
||||
|
||||
Color getPurposeLimitColor(int limit) {
|
||||
if (_counter.value <= limit) {
|
||||
return MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
} else {
|
||||
return MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
|
||||
}
|
||||
}
|
||||
|
||||
void successPopUp(
|
||||
MzansiProfileProvider profileProvider,
|
||||
String message,
|
||||
) {
|
||||
MihAlertServices().successAdvancedAlert(
|
||||
"Successfully Updated Profile",
|
||||
message,
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
if (profileProvider.user!.type.toLowerCase() == "business" &&
|
||||
profileProvider.business == null) {
|
||||
setupBusinessPopUp(profileProvider);
|
||||
} else {
|
||||
context.pop();
|
||||
context.pop();
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Dismiss",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
void setupBusinessPopUp(
|
||||
MzansiProfileProvider profileProvider,
|
||||
) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: null,
|
||||
onWindowTapClose: null,
|
||||
windowBody: Column(
|
||||
children: [
|
||||
Icon(
|
||||
MihIcons.businessSetup,
|
||||
size: 150,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
Text(
|
||||
"Setup Business Profile?",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Text(
|
||||
"It looks like this is the first time activating your business account. Would you like to set up your business now or would you like to do it later?",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
runAlignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
context.goNamed(
|
||||
'businessProfileSetup',
|
||||
extra: profileProvider.user,
|
||||
);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Setup Business",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
context.pop();
|
||||
context.pop();
|
||||
},
|
||||
buttonColor: MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Setup Later",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void notUniqueAlert() {
|
||||
MihAlertServices().errorBasicAlert(
|
||||
"Too Slow, That Username is Taken",
|
||||
"The username you have entered is already taken by another member of Mzansi. Please choose a different username and try again.",
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initializeControllers(context.read<MzansiProfileProvider>());
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Edit Profile",
|
||||
onWindowTapClose: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
windowBody: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: screenWidth * 0.05)
|
||||
: EdgeInsets.symmetric(horizontal: screenWidth * 0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
Center(
|
||||
child: MihCircleAvatar(
|
||||
imageFile: newSelectedProPic != null
|
||||
? MemoryImage(newSelectedProPic!.bytes!)
|
||||
: mzansiProfileProvider.userProfilePicture,
|
||||
width: 150,
|
||||
editable: true,
|
||||
fileNameController: proPicController,
|
||||
userSelectedfile: newSelectedProPic,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onChange: (selectedImage) {
|
||||
setState(() {
|
||||
newSelectedProPic = selectedImage;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
// const SizedBox(height: 25.0),
|
||||
Visibility(
|
||||
visible: false,
|
||||
child: MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: proPicController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
readOnly: true,
|
||||
hintText: "Selected File Name",
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: usernameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Username",
|
||||
validator: (value) {
|
||||
return MihValidationServices().validateUsername(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: fnameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "First Name",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: lnameController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Last Name",
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihTextFormField(
|
||||
height: 250,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: purposeController,
|
||||
multiLineInput: true,
|
||||
requiredText: true,
|
||||
hintText: "Your Personal Mission",
|
||||
validator: (value) {
|
||||
return MihValidationServices()
|
||||
.validateLength(purposeController.text, 256);
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
height: 15,
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: _counter,
|
||||
builder:
|
||||
(BuildContext context, int value, Widget? child) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Text(
|
||||
"$value",
|
||||
style: TextStyle(
|
||||
color: getPurposeLimitColor(256),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text(
|
||||
"/256",
|
||||
style: TextStyle(
|
||||
color: getPurposeLimitColor(256),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihToggle(
|
||||
hintText: "Activate Business Account",
|
||||
initialPostion: businessUser,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
secondaryFillColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onChange: (value) {
|
||||
setState(() {
|
||||
businessUser = value;
|
||||
});
|
||||
KenLogger.success("Business User: $businessUser");
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 30.0),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
//Add validation here
|
||||
if (_formKey.currentState!.validate()) {
|
||||
submitForm(mzansiProfileProvider);
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
mzansiProfileProvider.user!.username.isEmpty
|
||||
? "Setup Profile"
|
||||
: "Update",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.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:provider/provider.dart';
|
||||
|
||||
class MzansiProfile extends StatefulWidget {
|
||||
const MzansiProfile({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiProfile> createState() => _MzansiProfileState();
|
||||
}
|
||||
|
||||
class _MzansiProfileState extends State<MzansiProfile> {
|
||||
bool _isLoadingInitialData = true;
|
||||
late final MihPersonalProfile _personalProfile;
|
||||
late final MihPersonalSettings _personalSettings;
|
||||
|
||||
Future<void> _loadInitialData() async {
|
||||
setState(() {
|
||||
_isLoadingInitialData = true;
|
||||
});
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
if (mzansiProfileProvider.user == null) {
|
||||
await MihDataHelperServices().loadUserDataWithBusinessesData(
|
||||
mzansiProfileProvider,
|
||||
);
|
||||
}
|
||||
setState(() {
|
||||
_isLoadingInitialData = false;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_personalProfile = const MihPersonalProfile();
|
||||
_personalSettings = const MihPersonalSettings();
|
||||
_loadInitialData();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context, MzansiProfileProvider profileProvider,
|
||||
Widget? child) {
|
||||
if (_isLoadingInitialData) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Mihloadingcircle(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: profileProvider.personalIndex,
|
||||
onIndexChange: (newIndex) {
|
||||
profileProvider.setPersonalIndex(newIndex);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
// Navigator.of(context).pop();
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
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)] = () {
|
||||
context.read<MzansiProfileProvider>().setPersonalIndex(1);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MzansiProfileProvider>().personalIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_personalProfile,
|
||||
_personalSettings,
|
||||
];
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Profile",
|
||||
"Settings",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_profile_view.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MzansiProfileView extends StatefulWidget {
|
||||
const MzansiProfileView({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiProfileView> createState() => _MzansiProfileViewState();
|
||||
}
|
||||
|
||||
class _MzansiProfileViewState extends State<MzansiProfileView> {
|
||||
int _selcetedIndex = 0;
|
||||
late final MihPersonalProfileView _personalProfileView;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_personalProfileView = MihPersonalProfileView();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: _selcetedIndex,
|
||||
onIndexChange: (newValue) {
|
||||
setState(() {
|
||||
_selcetedIndex = newValue;
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.pop();
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.person)] = () {
|
||||
setState(() {
|
||||
_selcetedIndex = 0;
|
||||
});
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: _selcetedIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_personalProfileView,
|
||||
];
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Profile",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import 'package:go_router/go_router.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_package_components/mih_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MzansiProfileTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
|
||||
const MzansiProfileTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiProfileTile> createState() => _MzansiProfileTileState();
|
||||
}
|
||||
|
||||
class _MzansiProfileTileState extends State<MzansiProfileTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// ImageProvider logo = MzansiInnovationHub.of(context)!.theme.logoImage();
|
||||
return MihPackageTile(
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mzansiProfileManage',
|
||||
);
|
||||
},
|
||||
appName: "Mzansi Profile",
|
||||
appIcon: Icon(
|
||||
MihIcons.mihLogo,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: widget.packageSize,
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import 'package:go_router/go_router.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_package_components/mih_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MzansiSetupProfileTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
|
||||
const MzansiSetupProfileTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MzansiSetupProfileTile> createState() => _MzansiSetupProfileTileState();
|
||||
}
|
||||
|
||||
class _MzansiSetupProfileTileState extends State<MzansiSetupProfileTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageTile(
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mzansiProfileManage',
|
||||
);
|
||||
},
|
||||
appName: "Set Up Profile",
|
||||
appIcon: Icon(
|
||||
MihIcons.profileSetup,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: widget.packageSize,
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
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';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/components/mih_edit_personal_profile_window.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihPersonalProfile extends StatefulWidget {
|
||||
const MihPersonalProfile({super.key});
|
||||
|
||||
@override
|
||||
State<MihPersonalProfile> createState() => _MihPersonalProfileState();
|
||||
}
|
||||
|
||||
class _MihPersonalProfileState extends State<MihPersonalProfile> {
|
||||
TextEditingController proPicController = TextEditingController();
|
||||
PlatformFile? newSelectedProPic;
|
||||
|
||||
void editProfileWindow(double width) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return MihEditPersonalProfileWindow();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<ProfileLink> 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,
|
||||
bodyItem: getBody(screenWidth),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
if (mzansiProfileProvider.user == null) {
|
||||
//Change to new user flow
|
||||
return Center(
|
||||
child: Mihloadingcircle(),
|
||||
);
|
||||
} else {
|
||||
return MihSingleChildScroll(
|
||||
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: [
|
||||
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
|
||||
? mzansiProfileProvider.user!.username
|
||||
: "username",
|
||||
style: TextStyle(
|
||||
fontSize: 35,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
mzansiProfileProvider.user!.fname.isNotEmpty
|
||||
? "${mzansiProfileProvider.user!.fname} ${mzansiProfileProvider.user!.lname}"
|
||||
: "Name Surname",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
mzansiProfileProvider.user!.type == "business"
|
||||
? "Business".toUpperCase()
|
||||
: "Personal".toUpperCase(),
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
Center(
|
||||
child: SizedBox(
|
||||
width: 700,
|
||||
child: Text(
|
||||
mzansiProfileProvider.user!.purpose.isNotEmpty
|
||||
? mzansiProfileProvider.user!.purpose
|
||||
: "",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
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"),
|
||||
width: 35,
|
||||
height: 35,
|
||||
child: Icon(
|
||||
Icons.link,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_icons.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_services/mih_file_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.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:provider/provider.dart';
|
||||
|
||||
class MihPersonalProfileView extends StatefulWidget {
|
||||
const MihPersonalProfileView({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihPersonalProfileView> createState() => _MihPersonalProfileViewState();
|
||||
}
|
||||
|
||||
class _MihPersonalProfileViewState extends State<MihPersonalProfileView> {
|
||||
late Future<String> futureImageUrl;
|
||||
PlatformFile? file;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
MzansiDirectoryProvider directoryProvider =
|
||||
context.read<MzansiDirectoryProvider>();
|
||||
futureImageUrl = MihFileApi.getMinioFileUrl(
|
||||
directoryProvider.selectedUser!.pro_pic_path);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double screenWidth = MediaQuery.of(context).size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(screenWidth),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
double profilePictureWidth = 150;
|
||||
return Consumer<MzansiDirectoryProvider>(
|
||||
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
|
||||
Widget? child) {
|
||||
return MihSingleChildScroll(
|
||||
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,
|
||||
editable: false,
|
||||
fileNameController: TextEditingController(),
|
||||
userSelectedfile: file,
|
||||
frameColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
backgroundColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onChange: () {},
|
||||
);
|
||||
} else {
|
||||
return Icon(
|
||||
MihIcons.iDontKnow,
|
||||
size: profilePictureWidth,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return Icon(
|
||||
MihIcons.mihRing,
|
||||
size: profilePictureWidth,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
);
|
||||
}
|
||||
}),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
directoryProvider.selectedUser!.username.isNotEmpty
|
||||
? directoryProvider.selectedUser!.username
|
||||
: "Username",
|
||||
style: TextStyle(
|
||||
fontSize: 35,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
directoryProvider.selectedUser!.fname.isNotEmpty
|
||||
? "${directoryProvider.selectedUser!.fname} ${directoryProvider.selectedUser!.lname}"
|
||||
: "Name Surname",
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
directoryProvider.selectedUser!.type.toUpperCase(),
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
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.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30.0),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_single_child_scroll.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihPersonalSettings extends StatefulWidget {
|
||||
const MihPersonalSettings({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihPersonalSettings> createState() => _MihPersonalSettingsState();
|
||||
}
|
||||
|
||||
class _MihPersonalSettingsState extends State<MihPersonalSettings> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiProfileProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
innerHorizontalPadding: 10,
|
||||
bodyItem: getBody(mzansiProfileProvider),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void deleteAccountPopUp(
|
||||
MzansiProfileProvider mzansiProfileProvider, BuildContext ctxtd) {
|
||||
MihAlertServices().errorAdvancedAlert(
|
||||
"Are you sure you want to permanently delete your MIH account?",
|
||||
"This action will remove all of your data, and it cannot be recovered. We understand this is a big decision, so please take a moment to double-check.\n\nIf you're certain, please confirm below. If you've changed your mind, you can simply close this window.",
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
MihUserServices.deleteAccount(mzansiProfileProvider, context);
|
||||
},
|
||||
buttonColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Delete",
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
ctxtd,
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(MzansiProfileProvider mzansiProfileProvider) {
|
||||
return MihSingleChildScroll(
|
||||
child: Column(
|
||||
children: [
|
||||
Center(
|
||||
child: FaIcon(
|
||||
FontAwesomeIcons.trashCan,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
size: 150,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
Text(
|
||||
"Would you like to delete your MIH account?",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10.0),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
deleteAccountPopUp(mzansiProfileProvider, context);
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Delete Account",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,840 @@
|
||||
import 'package:flutter/foundation.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: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_icons.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_wallet_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_wallet_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/loyalty_card.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/components/mih_card_display.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:barcode_widget/barcode_widget.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:screen_brightness/screen_brightness.dart';
|
||||
|
||||
class BuildLoyaltyCardList extends StatefulWidget {
|
||||
final List<MIHLoyaltyCard> cardList;
|
||||
final int navIndex;
|
||||
final bool favouritesMode;
|
||||
final TextEditingController searchText;
|
||||
|
||||
const BuildLoyaltyCardList({
|
||||
super.key,
|
||||
required this.cardList,
|
||||
required this.navIndex,
|
||||
required this.favouritesMode,
|
||||
required this.searchText,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BuildLoyaltyCardList> createState() => _BuildLoyaltyCardListState();
|
||||
}
|
||||
|
||||
class _BuildLoyaltyCardListState extends State<BuildLoyaltyCardList> {
|
||||
final TextEditingController _nicknameController = TextEditingController();
|
||||
final TextEditingController _cardNumberController = TextEditingController();
|
||||
late int _noFavourites;
|
||||
double? _originalBrightness;
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
void openscanner() async {
|
||||
context.pushNamed(
|
||||
"barcodeScanner",
|
||||
extra: _cardNumberController,
|
||||
);
|
||||
}
|
||||
|
||||
void editCardWindow(
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MzansiWalletProvider walletProvider,
|
||||
BuildContext ctxt,
|
||||
int index,
|
||||
double width) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Edit Loyalty Card",
|
||||
onWindowTapClose: () {
|
||||
_cardNumberController.clear();
|
||||
_nicknameController.clear();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
windowBody: Padding(
|
||||
padding:
|
||||
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.05)
|
||||
: EdgeInsets.symmetric(horizontal: width * 0),
|
||||
child: Column(
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
controller: _nicknameController,
|
||||
multiLineInput: false,
|
||||
requiredText: false,
|
||||
hintText: "Card Title",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
child: MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: _cardNumberController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Card Number",
|
||||
numberMode: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
openscanner();
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 100,
|
||||
child: Text(
|
||||
"Scan",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
int statusCode = await MIHMzansiWalletApis
|
||||
.updateLoyaltyCardAPICall(
|
||||
walletProvider,
|
||||
mzansiProfileProvider.user!,
|
||||
widget.cardList[index].idloyalty_cards,
|
||||
widget.cardList[index].shop_name,
|
||||
widget.cardList[index].favourite,
|
||||
widget.cardList[index].priority_index,
|
||||
_nicknameController.text,
|
||||
_cardNumberController.text,
|
||||
ctxt,
|
||||
);
|
||||
if (statusCode == 200) {
|
||||
context.pop();
|
||||
context.pop();
|
||||
MihAlertServices().successBasicAlert(
|
||||
"Success!",
|
||||
"You have successfully updated the loyalty card details.",
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Update",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void deleteCardWindow(MzansiProfileProvider mzansiProfileProvider,
|
||||
MzansiWalletProvider walletProvider, BuildContext ctxt, int index) {
|
||||
MihAlertServices().deleteConfirmationAlert(
|
||||
"This Card will be deleted permanently from your Mzansi Wallet. Are you certain you want to delete it?",
|
||||
() async {
|
||||
int statusCode = await MIHMzansiWalletApis.deleteLoyaltyCardAPICall(
|
||||
walletProvider,
|
||||
mzansiProfileProvider.user!,
|
||||
widget.cardList[index].idloyalty_cards,
|
||||
context,
|
||||
);
|
||||
if (statusCode == 200) {
|
||||
context.pop();
|
||||
context.pop();
|
||||
MihAlertServices().successBasicAlert(
|
||||
"Success!",
|
||||
"You have successfully deleted the loyalty card from your Mzansi Wallet.",
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
context.pop();
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
},
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
void addToFavCardWindow(MzansiProfileProvider mzansiProfileProvider,
|
||||
MzansiWalletProvider walletProvider, BuildContext ctxt, int index) {
|
||||
MihAlertServices().warningAdvancedAlert(
|
||||
// "Card Added to Favourites",
|
||||
"Add Card to Favourites?",
|
||||
"Would you like to add this card to your favourites for quick access?",
|
||||
// "You have successfully added the loyalty card to your favourites.",
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () async {
|
||||
context.pop();
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () async {
|
||||
int statusCode = await MIHMzansiWalletApis.updateLoyaltyCardAPICall(
|
||||
walletProvider,
|
||||
mzansiProfileProvider.user!,
|
||||
widget.cardList[index].idloyalty_cards,
|
||||
widget.cardList[index].shop_name,
|
||||
"Yes",
|
||||
_noFavourites,
|
||||
widget.cardList[index].nickname,
|
||||
widget.cardList[index].card_number,
|
||||
ctxt,
|
||||
);
|
||||
if (statusCode == 200) {
|
||||
context.pop();
|
||||
context.pop();
|
||||
await MIHMzansiWalletApis.getFavouriteLoyaltyCards(
|
||||
walletProvider,
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
context,
|
||||
);
|
||||
context.read<MzansiWalletProvider>().setToolIndex(1);
|
||||
MihAlertServices().successBasicAlert(
|
||||
"Success!",
|
||||
"You have successfully added the loyalty card to your favourites.",
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Add",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
void removeFromFavCardWindow(MzansiProfileProvider mzansiProfileProvider,
|
||||
MzansiWalletProvider walletProvider, BuildContext ctxt, int index) {
|
||||
MihAlertServices().warningAdvancedAlert(
|
||||
"Remove From Favourites?",
|
||||
"Are you sure you want to remove this card from your favourites?",
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () async {
|
||||
int statusCode = await MIHMzansiWalletApis.updateLoyaltyCardAPICall(
|
||||
walletProvider,
|
||||
mzansiProfileProvider.user!,
|
||||
widget.cardList[index].idloyalty_cards,
|
||||
widget.cardList[index].shop_name,
|
||||
"",
|
||||
0,
|
||||
widget.cardList[index].nickname,
|
||||
widget.cardList[index].card_number,
|
||||
ctxt,
|
||||
);
|
||||
if (statusCode == 200) {
|
||||
context.pop();
|
||||
context.pop();
|
||||
await MIHMzansiWalletApis.getFavouriteLoyaltyCards(
|
||||
walletProvider,
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
context,
|
||||
);
|
||||
context.read<MzansiWalletProvider>().setToolIndex(0);
|
||||
MihAlertServices().successBasicAlert(
|
||||
"Success!",
|
||||
"You have successfully removed the loyalty card to your favourites.",
|
||||
context,
|
||||
);
|
||||
} else {
|
||||
MihAlertServices().internetConnectionAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Remove",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () async {
|
||||
context.pop();
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
ctxt,
|
||||
);
|
||||
}
|
||||
|
||||
void viewCardWindow(MzansiProfileProvider mzansiProfileProvider,
|
||||
MzansiWalletProvider walletProvider, int index, double width) {
|
||||
//print(widget.cardList[index].card_number);
|
||||
String formattedCardNumber = "";
|
||||
for (int i = 0; i <= widget.cardList[index].card_number.length - 1; i++) {
|
||||
formattedCardNumber += widget.cardList[index].card_number[i];
|
||||
if ((i + 1) % 4 == 0) {
|
||||
formattedCardNumber += "\t";
|
||||
}
|
||||
}
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: widget.cardList[index].shop_name.toUpperCase(),
|
||||
menuOptions: [
|
||||
SpeedDialChild(
|
||||
child: widget.cardList[index].favourite == ""
|
||||
? Icon(
|
||||
Icons.favorite,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
)
|
||||
: Icon(
|
||||
Icons.favorite_border,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: widget.cardList[index].favourite == ""
|
||||
? "Add to Favourite"
|
||||
: "Remove from Favourite",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
if (widget.cardList[index].favourite == "") {
|
||||
addToFavCardWindow(
|
||||
mzansiProfileProvider,
|
||||
walletProvider,
|
||||
context,
|
||||
index,
|
||||
);
|
||||
} else {
|
||||
removeFromFavCardWindow(
|
||||
mzansiProfileProvider,
|
||||
walletProvider,
|
||||
context,
|
||||
index,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Edit Card Details",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_cardNumberController.text = widget.cardList[index].card_number;
|
||||
_nicknameController.text = widget.cardList[index].nickname;
|
||||
});
|
||||
editCardWindow(
|
||||
mzansiProfileProvider,
|
||||
walletProvider,
|
||||
context,
|
||||
index,
|
||||
width,
|
||||
);
|
||||
},
|
||||
),
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.delete,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
label: "Delete Card",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onTap: () {
|
||||
deleteCardWindow(
|
||||
mzansiProfileProvider,
|
||||
walletProvider,
|
||||
context,
|
||||
index,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onWindowTapClose: () {
|
||||
resetScreenBrightness();
|
||||
context.pop();
|
||||
},
|
||||
windowBody: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Container(
|
||||
width: 500,
|
||||
child: MihCardDisplay(
|
||||
shopName: widget.cardList[index].shop_name,
|
||||
nickname: widget.cardList[index].nickname,
|
||||
height: 250,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Container(
|
||||
width: 500,
|
||||
//color: Colors.white,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// const SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: SizedBox(
|
||||
height: 75,
|
||||
// width: 300,
|
||||
child: BarcodeWidget(
|
||||
//color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
barcode: Barcode.code128(),
|
||||
backgroundColor: Colors.white,
|
||||
data: widget.cardList[index].card_number,
|
||||
drawText: false,
|
||||
),
|
||||
// SfBarcodeGenerator(
|
||||
// backgroundColor: Colors.white,
|
||||
// barColor: Colors.black,
|
||||
// value: widget.cardList[index].card_number,
|
||||
// symbology: Code128(),
|
||||
// //showValue: true,
|
||||
// ),
|
||||
),
|
||||
),
|
||||
// const SizedBox(height: 10),
|
||||
Text(
|
||||
formattedCardNumber,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold
|
||||
//MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10),
|
||||
MihBannerAd()
|
||||
// MihBannerAd(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
double getHorizontalPaddingSize(Size screenSize) {
|
||||
if (MzansiInnovationHub.of(context)!.theme.screenType == "desktop") {
|
||||
return screenSize.width / 10;
|
||||
} else {
|
||||
return 20;
|
||||
}
|
||||
}
|
||||
|
||||
int countFavourites() {
|
||||
int count = 0;
|
||||
for (var card in widget.cardList) {
|
||||
if (card.favourite != "") {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
Future<void> setScreenBrightness(double newBrightness) async {
|
||||
if (!kIsWeb) {
|
||||
bool canChange =
|
||||
await ScreenBrightness.instance.canChangeSystemBrightness;
|
||||
|
||||
KenLogger.success("Can change system brightness: $canChange");
|
||||
if (canChange) {
|
||||
// Permission is granted, you can now change the system brightness
|
||||
await ScreenBrightness.instance.system.then((brightness) {
|
||||
setState(() {
|
||||
_originalBrightness = brightness;
|
||||
});
|
||||
KenLogger.success("Original brightness: $_originalBrightness");
|
||||
});
|
||||
await ScreenBrightness.instance
|
||||
.setSystemScreenBrightness(newBrightness);
|
||||
KenLogger.success("Brightness set to: $newBrightness");
|
||||
} else {
|
||||
context.pop();
|
||||
MihAlertServices().errorAdvancedAlert(
|
||||
"Permission Required",
|
||||
"Sometimes it can be tough to scan your loyalty card if your phone screen is dim. To make sure your scan is successful every time, we need your permission to temporarily increase your screen brightness.\n\nWould you mind enabling this in your device settings?",
|
||||
[
|
||||
MihButton(
|
||||
onPressed: () async {
|
||||
context.pop();
|
||||
await ScreenBrightness.instance
|
||||
.setSystemScreenBrightness(newBrightness);
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Grant Permission",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
context,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
KenLogger.warning(
|
||||
"Screen brightness adjustment is not supported on Web.");
|
||||
// _originalBrightness = 1.0; // Default brightness for web
|
||||
// await ScreenBrightness.instance.setSystemScreenBrightness(1.0);
|
||||
// KenLogger.success("Brightness set to default value: 1.0");
|
||||
}
|
||||
}
|
||||
|
||||
void resetScreenBrightness() async {
|
||||
if (!kIsWeb) {
|
||||
KenLogger.success(
|
||||
"Resetting screen brightness to original value: $_originalBrightness");
|
||||
if (_originalBrightness != null) {
|
||||
await ScreenBrightness.instance
|
||||
.setSystemScreenBrightness(_originalBrightness!);
|
||||
}
|
||||
} else {
|
||||
KenLogger.warning("Screen brightness reset is not supported on Web.");
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
setState(() {
|
||||
_noFavourites = countFavourites();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
// final double width = size.width;
|
||||
//final double height = size.height;
|
||||
if (widget.cardList.isNotEmpty) {
|
||||
return Consumer2<MzansiProfileProvider, MzansiWalletProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MzansiWalletProvider walletProvider,
|
||||
Widget? child) {
|
||||
return GridView.builder(
|
||||
padding: EdgeInsets.only(
|
||||
left: getHorizontalPaddingSize(size),
|
||||
right: getHorizontalPaddingSize(size),
|
||||
),
|
||||
itemCount: widget.cardList.length,
|
||||
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
mainAxisSpacing: 0,
|
||||
crossAxisSpacing: 5,
|
||||
maxCrossAxisExtent: 200,
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
return GestureDetector(
|
||||
child: MihCardDisplay(
|
||||
shopName: widget.cardList[index].shop_name,
|
||||
nickname: widget.cardList[index].nickname,
|
||||
height: 100,
|
||||
),
|
||||
onTap: () {
|
||||
setScreenBrightness(1.0);
|
||||
viewCardWindow(
|
||||
mzansiProfileProvider,
|
||||
walletProvider,
|
||||
index,
|
||||
size.width,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
if (!widget.favouritesMode) {
|
||||
if (widget.searchText.text.isNotEmpty) {
|
||||
return Column(
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.iDontKnow,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Let's try refining your search",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.mzansiWallet,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"No cards added to your Mzansi Wallet",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
Icons.menu,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(text: " to add your first loyalty card"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(height: 50),
|
||||
Icon(
|
||||
MihIcons.mzansiWallet,
|
||||
size: 165,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"No favourite cards in your Mzansi Wallet",
|
||||
textAlign: TextAlign.center,
|
||||
overflow: TextOverflow.visible,
|
||||
style: TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Center(
|
||||
child: RichText(
|
||||
textAlign: TextAlign.center,
|
||||
text: TextSpan(
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.normal,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
children: [
|
||||
TextSpan(text: "Press "),
|
||||
WidgetSpan(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
child: Icon(
|
||||
Icons.menu,
|
||||
size: 20,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text:
|
||||
" when viewing a loyalty card to add it to your favorites"),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_dropdwn_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_form.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_text_form_field.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_wallet_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/components/mih_card_display.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_wallet_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihAddCardWindow extends StatefulWidget {
|
||||
const MihAddCardWindow({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihAddCardWindow> createState() => _MihAddCardWindowState();
|
||||
}
|
||||
|
||||
class _MihAddCardWindowState extends State<MihAddCardWindow> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final TextEditingController _cardNumberController = TextEditingController();
|
||||
final TextEditingController _shopController = TextEditingController();
|
||||
final TextEditingController _nicknameController = TextEditingController();
|
||||
final ValueNotifier<String> _shopName = ValueNotifier("");
|
||||
|
||||
void successPopUp(String title, String message, int packageIndex) {
|
||||
MihAlertServices().successBasicAlert(
|
||||
title,
|
||||
message,
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_cardNumberController.dispose();
|
||||
_shopController.dispose();
|
||||
_nicknameController.dispose();
|
||||
_shopName.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_shopController.addListener(_shopSelected);
|
||||
}
|
||||
|
||||
void _shopSelected() {
|
||||
if (_shopController.text.isNotEmpty) {
|
||||
_shopName.value = _shopController.text;
|
||||
} else {
|
||||
_shopName.value = "";
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double width = MediaQuery.sizeOf(context).width;
|
||||
return MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle: "Add New Loyalty Card",
|
||||
onWindowTapClose: () {
|
||||
_shopController.clear();
|
||||
_cardNumberController.clear();
|
||||
_nicknameController.clear();
|
||||
_shopName.value = "";
|
||||
Navigator.pop(context);
|
||||
},
|
||||
windowBody: Padding(
|
||||
padding: MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
|
||||
? EdgeInsets.symmetric(horizontal: width * 0.05)
|
||||
: EdgeInsets.symmetric(horizontal: width * 0),
|
||||
child: Consumer2<MzansiProfileProvider, MzansiWalletProvider>(
|
||||
builder: (BuildContext context,
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MzansiWalletProvider walletProvider,
|
||||
Widget? child) {
|
||||
return Column(
|
||||
children: [
|
||||
MihForm(
|
||||
formKey: _formKey,
|
||||
formFields: [
|
||||
MihDropdownField(
|
||||
controller: _shopController,
|
||||
hintText: "Shop Name",
|
||||
editable: true,
|
||||
enableSearch: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
requiredText: true,
|
||||
dropdownOptions: const <String>[
|
||||
"+More",
|
||||
"Apple Tree",
|
||||
"Auchan",
|
||||
"Best Before",
|
||||
"Big Save",
|
||||
"Boxer",
|
||||
"BP",
|
||||
"Builders Warehouse",
|
||||
"Checkers",
|
||||
"Choppies",
|
||||
"Clicks",
|
||||
"Continente",
|
||||
"Cotton:On",
|
||||
"Carrefour",
|
||||
"Dis-Chem",
|
||||
"Edgars",
|
||||
"Engen",
|
||||
"Eskom",
|
||||
"Exclusive Books",
|
||||
"Fresh Stop",
|
||||
"Fresmart",
|
||||
"Infinity",
|
||||
"Jet",
|
||||
"Justrite",
|
||||
"Kero",
|
||||
"Leroy Merlin",
|
||||
"Makro",
|
||||
"Naivas",
|
||||
"OK Foods",
|
||||
"Panarottis",
|
||||
"Pick n Pay",
|
||||
"PnA",
|
||||
"PQ Clothing",
|
||||
"Rage",
|
||||
"Sefalana",
|
||||
"Sasol",
|
||||
"Shell",
|
||||
"Shoprite",
|
||||
"Signature Cosmetics & Fragrances",
|
||||
"Spar",
|
||||
"Spur",
|
||||
"TFG Group",
|
||||
"Total Energies",
|
||||
"Toys R Us",
|
||||
"Woermann Brock",
|
||||
"Woolworths",
|
||||
],
|
||||
),
|
||||
ValueListenableBuilder(
|
||||
valueListenable: _shopName,
|
||||
builder:
|
||||
(BuildContext context, String value, Widget? child) {
|
||||
return Visibility(
|
||||
visible: value != "",
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
MihCardDisplay(
|
||||
shopName: _shopName.value,
|
||||
nickname: "",
|
||||
height: 200),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: _nicknameController,
|
||||
multiLineInput: false,
|
||||
requiredText: false,
|
||||
hintText: "Card Title",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
child: MihTextFormField(
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
inputColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
controller: _cardNumberController,
|
||||
multiLineInput: false,
|
||||
requiredText: true,
|
||||
hintText: "Card Number",
|
||||
numberMode: true,
|
||||
validator: (value) {
|
||||
return MihValidationServices().isEmpty(value);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 20),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.pushNamed(
|
||||
"barcodeScanner",
|
||||
extra:
|
||||
_cardNumberController, // Use local controller
|
||||
);
|
||||
},
|
||||
buttonColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 100,
|
||||
child: Text(
|
||||
"Scan",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Center(
|
||||
child: MihButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
if (_shopController.text == "") {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
} else {
|
||||
int statusCode = await MIHMzansiWalletApis
|
||||
.addLoyaltyCardAPICall(
|
||||
walletProvider,
|
||||
mzansiProfileProvider.user!,
|
||||
mzansiProfileProvider.user!.app_id,
|
||||
_shopController.text,
|
||||
_cardNumberController.text,
|
||||
"",
|
||||
0,
|
||||
_nicknameController.text,
|
||||
context,
|
||||
);
|
||||
if (statusCode == 201) {
|
||||
context.pop();
|
||||
KenLogger.success("Card Added Successfully");
|
||||
successPopUp(
|
||||
"Successfully Added Card",
|
||||
"The loyalty card has been added to your favourites.",
|
||||
0,
|
||||
);
|
||||
} else {
|
||||
MihAlertServices()
|
||||
.internetConnectionAlert(context);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MihAlertServices().inputErrorAlert(context);
|
||||
}
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Add",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MihBarcodeScanner extends StatefulWidget {
|
||||
final TextEditingController cardNumberController;
|
||||
const MihBarcodeScanner({
|
||||
super.key,
|
||||
required this.cardNumberController,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihBarcodeScanner> createState() => _MihBarcodeScannerState();
|
||||
}
|
||||
|
||||
class _MihBarcodeScannerState extends State<MihBarcodeScanner>
|
||||
with WidgetsBindingObserver {
|
||||
final MobileScannerController _scannerController = MobileScannerController(
|
||||
detectionSpeed: DetectionSpeed.normal,
|
||||
);
|
||||
StreamSubscription<Object>? _subscription;
|
||||
bool _isScannerStarting = false;
|
||||
bool barcodeScanned = false;
|
||||
|
||||
Future<void> foundCode(BarcodeCapture bcode) async {
|
||||
if (mounted &&
|
||||
barcodeScanned == false &&
|
||||
bcode.barcodes.isNotEmpty &&
|
||||
bcode.barcodes.first.rawValue != null) {
|
||||
setState(() {
|
||||
barcodeScanned = true;
|
||||
widget.cardNumberController.text = bcode.barcodes.first.rawValue!;
|
||||
});
|
||||
print(bcode.barcodes.first.rawValue);
|
||||
await _scannerController.stop();
|
||||
if (mounted) {
|
||||
context.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
if (!_scannerController.value.hasCameraPermission) {
|
||||
return;
|
||||
}
|
||||
switch (state) {
|
||||
case AppLifecycleState.detached:
|
||||
case AppLifecycleState.hidden:
|
||||
case AppLifecycleState.paused:
|
||||
return;
|
||||
case AppLifecycleState.resumed:
|
||||
if (!_scannerController.value.isRunning && !_isScannerStarting) {
|
||||
_isScannerStarting = true;
|
||||
_subscription = _scannerController.barcodes.listen(foundCode);
|
||||
unawaited(_scannerController.start().then((_) {
|
||||
_isScannerStarting = false;
|
||||
}));
|
||||
}
|
||||
case AppLifecycleState.inactive:
|
||||
unawaited(_subscription?.cancel());
|
||||
_subscription = null;
|
||||
unawaited(_scannerController.stop().then((_) {
|
||||
_isScannerStarting = false;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
unawaited(_subscription?.cancel());
|
||||
_subscription = null;
|
||||
_scannerController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
_subscription = _scannerController.barcodes.listen(foundCode);
|
||||
// unawaited(_scannerController.start());
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
MobileScanner(
|
||||
controller: _scannerController,
|
||||
onDetect: foundCode,
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Container(
|
||||
width: 500,
|
||||
height: 150,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 5,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: AlignmentDirectional.bottomCenter,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: MihButton(
|
||||
onPressed: () {
|
||||
_scannerController.stop();
|
||||
context.pop();
|
||||
},
|
||||
buttonColor: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
width: 100,
|
||||
height: 50,
|
||||
child: Text(
|
||||
"Cancel",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// GestureDetector(
|
||||
// onTap: () {
|
||||
// scannerController.stop();
|
||||
// Navigator.of(context).pop();
|
||||
// },
|
||||
// child: const Text(
|
||||
// "Cancel",
|
||||
// style: TextStyle(
|
||||
// fontWeight: FontWeight.bold,
|
||||
// fontSize: 25,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// IconButton(
|
||||
// onPressed: () {},
|
||||
// icon: const Icon(
|
||||
// Icons.flip_camera_android,
|
||||
// size: 30,
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MihCardDisplay extends StatefulWidget {
|
||||
final String shopName;
|
||||
final String nickname;
|
||||
final double height;
|
||||
const MihCardDisplay({
|
||||
super.key,
|
||||
required this.shopName,
|
||||
required this.height,
|
||||
required this.nickname,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihCardDisplay> createState() => _MihCardDisplayState();
|
||||
}
|
||||
|
||||
class _MihCardDisplayState extends State<MihCardDisplay> {
|
||||
Widget? displayLoyaltyCard() {
|
||||
switch (widget.shopName.toLowerCase()) {
|
||||
case "apple tree":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/apple_tree-min.png');
|
||||
case "best before":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/best_before-min.png');
|
||||
case "checkers":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/checkers-min.png');
|
||||
case "clicks":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/clicks-min.png');
|
||||
case "cotton:on":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/cotton_on-min.png');
|
||||
case "dis-chem":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/dischem-min.png');
|
||||
case "pick n pay":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/pick_n_pay-min.png');
|
||||
case "shoprite":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/shoprite-min.png');
|
||||
case "spar":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/spar-min.png');
|
||||
case "woolworths":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/woolworths-min.png');
|
||||
case "makro":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/makro-min.png');
|
||||
case "fresh stop":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/fresh_stop-min.png');
|
||||
case "panarottis":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/panarottis-min.png');
|
||||
case "shell":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/shell-min.png');
|
||||
case "edgars":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/edgars-min.png');
|
||||
case "jet":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/jet-min.png');
|
||||
case "spur":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/spur-min.png');
|
||||
case "infinity":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/infinity-min.png');
|
||||
case "eskom":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/eskom-min.png');
|
||||
case "+more":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/plus_more-min.png');
|
||||
case "bp":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/bp-min.png');
|
||||
case "builders warehouse":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/builders-min.png');
|
||||
case "exclusive books":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/exclusive_books-min.png');
|
||||
case "pna":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/pna-min.png');
|
||||
case "pq clothing":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/pq-min.png');
|
||||
case "rage":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/rage-min.png');
|
||||
case "sasol":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/sasol-min.png');
|
||||
case "tfg group":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/tfg-min.png');
|
||||
case "toys r us":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/toysrus-min.png');
|
||||
case "leroy merlin":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/leroy_merlin-min.png');
|
||||
case "signature cosmetics & fragrances":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/signature_cosmetics-min.png');
|
||||
case "ok foods":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/ok_food-min.png');
|
||||
case "choppies":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/choppies-min.png');
|
||||
case "boxer":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/boxer-min.png');
|
||||
case "carrefour":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/carrefour-min.png');
|
||||
case "sefalana":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/sefalana-min.png');
|
||||
case "big save":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/big_save-min.png');
|
||||
case "justrite":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/justrite-min.png');
|
||||
case "naivas":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/naivas-min.png');
|
||||
case "kero":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/kero-min.png');
|
||||
case "auchan":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/auchan-min.png');
|
||||
case "woermann brock":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/woermann_brock-min.png');
|
||||
case "continente":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/continente-min.png');
|
||||
case "fresmart":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/fresmart-min.png');
|
||||
case "total energies":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/total_energies-min.png');
|
||||
case "engen":
|
||||
return Image.asset(
|
||||
'lib/mih_package_components/assets/images/loyalty_cards/mini/engen-min.png');
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Visibility(
|
||||
visible: displayLoyaltyCard() != null,
|
||||
child: Column(
|
||||
children: [
|
||||
displayLoyaltyCard() != null ? displayLoyaltyCard()! : SizedBox(),
|
||||
FittedBox(
|
||||
child: Text(
|
||||
widget.nickname,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
fontSize: 25,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
139
mih_ui/lib/mih_packages/mzansi_wallet/mih_wallet.dart
Normal file
139
mih_ui/lib/mih_packages/mzansi_wallet/mih_wallet.dart
Normal file
@@ -0,0 +1,139 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_wallet_provider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/package_tools/mih_card_favourites.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/package_tools/mih_cards.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_data_helper_services.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_wallet_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihWallet extends StatefulWidget {
|
||||
const MihWallet({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihWallet> createState() => _MihWalletState();
|
||||
}
|
||||
|
||||
class _MihWalletState extends State<MihWallet> {
|
||||
bool _isLoadingInitialData = true;
|
||||
late final MihCards _cards;
|
||||
late final MihCardFavourites _cardFavourites;
|
||||
|
||||
Future<void> _loadInitialData() async {
|
||||
setState(() {
|
||||
_isLoadingInitialData = true;
|
||||
});
|
||||
MzansiProfileProvider mzansiProfileProvider =
|
||||
context.read<MzansiProfileProvider>();
|
||||
MzansiWalletProvider walletProvider = context.read<MzansiWalletProvider>();
|
||||
if (mzansiProfileProvider.user == null) {
|
||||
await MihDataHelperServices().loadUserDataOnly(
|
||||
mzansiProfileProvider,
|
||||
);
|
||||
}
|
||||
await setLoyaltyCards(mzansiProfileProvider, walletProvider);
|
||||
await setFavouritesCards(mzansiProfileProvider, walletProvider);
|
||||
setState(() {
|
||||
_isLoadingInitialData = false;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> setLoyaltyCards(
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MzansiWalletProvider walletProvider,
|
||||
) async {
|
||||
await MIHMzansiWalletApis.getLoyaltyCards(
|
||||
walletProvider, mzansiProfileProvider.user!.app_id, context);
|
||||
}
|
||||
|
||||
Future<void> setFavouritesCards(
|
||||
MzansiProfileProvider mzansiProfileProvider,
|
||||
MzansiWalletProvider walletProvider,
|
||||
) async {
|
||||
await MIHMzansiWalletApis.getFavouriteLoyaltyCards(
|
||||
walletProvider, mzansiProfileProvider.user!.app_id, context);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_cards = MihCards();
|
||||
_cardFavourites = MihCardFavourites();
|
||||
_loadInitialData();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<MzansiWalletProvider>(
|
||||
builder: (BuildContext context, MzansiWalletProvider walletProvider,
|
||||
Widget? child) {
|
||||
if (_isLoadingInitialData) {
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Mihloadingcircle(),
|
||||
),
|
||||
);
|
||||
}
|
||||
return MihPackage(
|
||||
appActionButton: getAction(),
|
||||
appTools: getTools(),
|
||||
appBody: getToolBody(),
|
||||
appToolTitles: getToolTitle(),
|
||||
selectedbodyIndex: walletProvider.toolIndex,
|
||||
onIndexChange: (newIndex) {
|
||||
walletProvider.setToolIndex(newIndex);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageAction getAction() {
|
||||
return MihPackageAction(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
iconSize: 35,
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mihHome',
|
||||
);
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
MihPackageTools getTools() {
|
||||
Map<Widget, void Function()?> temp = {};
|
||||
temp[const Icon(Icons.card_membership)] = () {
|
||||
context.read<MzansiWalletProvider>().setToolIndex(0);
|
||||
};
|
||||
temp[const Icon(Icons.favorite)] = () {
|
||||
context.read<MzansiWalletProvider>().setToolIndex(1);
|
||||
};
|
||||
return MihPackageTools(
|
||||
tools: temp,
|
||||
selcetedIndex: context.watch<MzansiWalletProvider>().toolIndex,
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> getToolBody() {
|
||||
return [
|
||||
_cards,
|
||||
_cardFavourites,
|
||||
];
|
||||
}
|
||||
|
||||
List<String> getToolTitle() {
|
||||
List<String> toolTitles = [
|
||||
"Cards",
|
||||
"Favourites",
|
||||
];
|
||||
return toolTitles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:go_router/go_router.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_package_components/mih_icons.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
|
||||
class MihWalletTile extends StatefulWidget {
|
||||
final double packageSize;
|
||||
|
||||
const MihWalletTile({
|
||||
super.key,
|
||||
required this.packageSize,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihWalletTile> createState() => _MihWalletTileState();
|
||||
}
|
||||
|
||||
class _MihWalletTileState extends State<MihWalletTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageTile(
|
||||
// authenticateUser: true,
|
||||
onTap: () {
|
||||
context.goNamed(
|
||||
'mzansiWallet',
|
||||
);
|
||||
// Navigator.of(context).pushNamed(
|
||||
// '/mzansi-wallet',
|
||||
// arguments: WalletArguments(widget.signedInUser, 0),
|
||||
// );
|
||||
},
|
||||
appName: "Mzansi Wallet",
|
||||
appIcon: Icon(
|
||||
MihIcons.mzansiWallet,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
// size: widget.packageSize,
|
||||
),
|
||||
iconSize: widget.packageSize,
|
||||
textColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_wallet_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/loyalty_card.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/builder/build_loyalty_card_list.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihCardFavourites extends StatefulWidget {
|
||||
const MihCardFavourites({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihCardFavourites> createState() => _MihCardFavouritesState();
|
||||
}
|
||||
|
||||
class _MihCardFavouritesState extends State<MihCardFavourites> {
|
||||
late Future<List<MIHLoyaltyCard>> cardList;
|
||||
List<MIHLoyaltyCard> listOfCards = [];
|
||||
|
||||
void getFavouriteLoyaltyCards(BuildContext context) async {
|
||||
setState(() {
|
||||
listOfCards = context.read<MzansiWalletProvider>().favouriteCards;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
getFavouriteLoyaltyCards(context);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody() {
|
||||
return BuildLoyaltyCardList(
|
||||
cardList: listOfCards,
|
||||
navIndex: 0,
|
||||
favouritesMode: true,
|
||||
searchText: TextEditingController(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_providers/mzansi_wallet_provider.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/components/mih_add_card_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_package_tool_body.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_floating_menu.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_package_components/mih_search_bar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_objects/loyalty_card.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/builder/build_loyalty_card_list.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MihCards extends StatefulWidget {
|
||||
const MihCards({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
State<MihCards> createState() => _MihCardsState();
|
||||
}
|
||||
|
||||
class _MihCardsState extends State<MihCards> {
|
||||
final TextEditingController cardSearchController = TextEditingController();
|
||||
final FocusNode searchFocusNode = FocusNode();
|
||||
final ValueNotifier<List<MIHLoyaltyCard>> searchShopName = ValueNotifier([]);
|
||||
final MobileScannerController scannerController = MobileScannerController(
|
||||
detectionSpeed: DetectionSpeed.unrestricted,
|
||||
);
|
||||
final boxFit = BoxFit.contain;
|
||||
late MzansiWalletProvider _walletProvider;
|
||||
late VoidCallback _searchListener;
|
||||
|
||||
void searchShop(List<MIHLoyaltyCard> allCards) {
|
||||
if (cardSearchController.text.isEmpty) {
|
||||
searchShopName.value = allCards;
|
||||
} else {
|
||||
List<MIHLoyaltyCard> temp = [];
|
||||
for (var item in allCards) {
|
||||
if (item.shop_name
|
||||
.toLowerCase()
|
||||
.contains(cardSearchController.text.toLowerCase()) ||
|
||||
item.nickname
|
||||
.toLowerCase()
|
||||
.contains(cardSearchController.text.toLowerCase())) {
|
||||
temp.add(item);
|
||||
}
|
||||
}
|
||||
searchShopName.value = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void successPopUp(String title, String message, int packageIndex) {
|
||||
MihAlertServices().successBasicAlert(
|
||||
title,
|
||||
message,
|
||||
context,
|
||||
);
|
||||
}
|
||||
|
||||
void addCardWindow(BuildContext ctxt, double width) {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => MihAddCardWindow(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
cardSearchController.removeListener(_searchListener);
|
||||
cardSearchController.dispose();
|
||||
searchShopName.dispose();
|
||||
searchFocusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_walletProvider = context.read<MzansiWalletProvider>();
|
||||
_searchListener = () {
|
||||
searchShop(_walletProvider.loyaltyCards);
|
||||
};
|
||||
searchShopName.value = _walletProvider.loyaltyCards;
|
||||
cardSearchController.addListener(_searchListener);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Size size = MediaQuery.sizeOf(context);
|
||||
final double width = size.width;
|
||||
return MihPackageToolBody(
|
||||
borderOn: false,
|
||||
bodyItem: getBody(width),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getBody(double width) {
|
||||
return Consumer<MzansiWalletProvider>(
|
||||
builder: (BuildContext context, MzansiWalletProvider walletProvider,
|
||||
Widget? child) {
|
||||
if (cardSearchController.text.isEmpty) {
|
||||
searchShopName.value = walletProvider.loyaltyCards;
|
||||
} else {
|
||||
// Re-run search with updated card list
|
||||
searchShop(walletProvider.loyaltyCards);
|
||||
}
|
||||
return Stack(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: width / 20),
|
||||
child: MihSearchBar(
|
||||
controller: cardSearchController,
|
||||
hintText: "Search Cards",
|
||||
// prefixIcon: Icons.search,
|
||||
prefixIcon: Icons.search,
|
||||
fillColor: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
hintColor: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
|
||||
onPrefixIconTap: () {
|
||||
// print("Search Icon Pressed: ${cardSearchController.text}");
|
||||
},
|
||||
searchFocusNode: searchFocusNode,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Expanded(
|
||||
child: ValueListenableBuilder<List<MIHLoyaltyCard>>(
|
||||
valueListenable: searchShopName,
|
||||
builder: (context, filteredCards, child) {
|
||||
return BuildLoyaltyCardList(
|
||||
cardList: filteredCards, //listOfCards,
|
||||
navIndex: 0,
|
||||
favouritesMode: false,
|
||||
searchText: cardSearchController,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
right: 10,
|
||||
bottom: 10,
|
||||
child: MihFloatingMenu(
|
||||
animatedIcon: AnimatedIcons.menu_close,
|
||||
children: [
|
||||
SpeedDialChild(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
),
|
||||
label: "Add Loyalty Card",
|
||||
labelBackgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
labelStyle: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
backgroundColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!.theme.mode ==
|
||||
"Dark"),
|
||||
onTap: () {
|
||||
addCardWindow(context, width);
|
||||
},
|
||||
)
|
||||
]),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user