Merge pull request #260 from yaso-meth/V.1.2.2

V.1.2.2
This commit is contained in:
yaso-meth
2025-10-31 13:16:34 +02:00
committed by GitHub
176 changed files with 14518 additions and 11420 deletions

View File

@@ -55,6 +55,11 @@ android {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
}

View File

@@ -0,0 +1,5 @@
# R8/ProGuard rules to prevent removal of necessary Facebook Infer annotations
-keep class com.facebook.infer.annotation.** { *; }
-keep interface com.facebook.infer.annotation.** { *; }
-dontwarn com.facebook.infer.annotation.Nullsafe$Mode
-dontwarn com.facebook.infer.annotation.Nullsafe

View File

@@ -19,7 +19,8 @@
<application
android:label="MIH"
android:name="${applicationName}"
android:icon="@mipmap/launcher_icon">
android:icon="@mipmap/launcher_icon"
android:enableOnBackInvokedCallback="true">
<activity
android:name=".MainActivity"
android:exported="true"

View File

@@ -1,5 +1,5 @@
package za.co.mzansiinnovationhub.mih
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.android.FlutterFragmentActivity
class MainActivity : FlutterActivity()
class MainActivity : FlutterFragmentActivity()

View File

@@ -34,6 +34,7 @@ PODS:
- DKPhotoGallery/Resource (0.0.19):
- SDWebImage
- SwiftyGif
- FBAudienceNetwork (6.20.1)
- file_picker (0.0.1):
- DKImagePickerController/PhotoGallery
- Flutter
@@ -49,12 +50,18 @@ PODS:
- geolocator_apple (1.2.0):
- Flutter
- FlutterMacOS
- gma_mediation_meta (1.4.1):
- Flutter
- GoogleMobileAdsMediationFacebook (~> 6.20.1.0)
- Google-Mobile-Ads-SDK (12.2.0):
- GoogleUserMessagingPlatform (>= 1.1)
- google_mobile_ads (6.0.0):
- Flutter
- Google-Mobile-Ads-SDK (~> 12.2.0)
- webview_flutter_wkwebview
- GoogleMobileAdsMediationFacebook (6.20.1.0):
- FBAudienceNetwork (= 6.20.1)
- Google-Mobile-Ads-SDK (~> 12.0)
- GoogleUserMessagingPlatform (3.0.0)
- local_auth_darwin (0.0.1):
- Flutter
@@ -101,6 +108,7 @@ DEPENDENCIES:
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- flutter_tts (from `.symlinks/plugins/flutter_tts/ios`)
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
- gma_mediation_meta (from `.symlinks/plugins/gma_mediation_meta/ios`)
- google_mobile_ads (from `.symlinks/plugins/google_mobile_ads/ios`)
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
@@ -119,7 +127,9 @@ SPEC REPOS:
trunk:
- DKImagePickerController
- DKPhotoGallery
- FBAudienceNetwork
- Google-Mobile-Ads-SDK
- GoogleMobileAdsMediationFacebook
- GoogleUserMessagingPlatform
- SDWebImage
- SwiftyGif
@@ -143,6 +153,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/flutter_tts/ios"
geolocator_apple:
:path: ".symlinks/plugins/geolocator_apple/darwin"
gma_mediation_meta:
:path: ".symlinks/plugins/gma_mediation_meta/ios"
google_mobile_ads:
:path: ".symlinks/plugins/google_mobile_ads/ios"
local_auth_darwin:
@@ -175,6 +187,7 @@ SPEC CHECKSUMS:
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
FBAudienceNetwork: 08e86d63a05b3a5a59414af12e4af8d756943c80
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
fl_downloader: dc99aa8dd303f862cccb830087f37acc9b0156ee
@@ -182,8 +195,10 @@ SPEC CHECKSUMS:
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
flutter_tts: b88dbc8655d3dc961bc4a796e4e16a4cc1795833
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
gma_mediation_meta: 44defcf3b61414cdca65c0f897360e31b9332a09
Google-Mobile-Ads-SDK: 1dfb0c3cb46c7e2b00b0f4de74a1e06d9ea25d67
google_mobile_ads: 535223588a6791b7a3cc3513a1bc7b89d12f3e62
GoogleMobileAdsMediationFacebook: b11a92ae3bfdae19853b882252b7e62791c18162
GoogleUserMessagingPlatform: f8d0cdad3ca835406755d0a69aa634f00e76d576
local_auth_darwin: 553ce4f9b16d3fdfeafce9cf042e7c9f77c1c391
mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93

View File

@@ -2,6 +2,17 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SKAdNetworkItems</key>
<array>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>v9wttpbfk9.skadnetwork</string>
</dict>
<dict>
<key>SKAdNetworkIdentifier</key>
<string>n38lu8286q.skadnetwork</string>
</dict>
</array>
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-4781880856775334~6935644635</string>
<key>CADisableMinimumFrameDurationOnPhone</key>

View File

@@ -1,6 +1,19 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/about_mih_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_authentication_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calculator_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_wallet_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/patient_manager_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:provider/provider.dart';
import 'package:upgrader/upgrader.dart';
import 'mih_config/mih_env.dart';
import 'mih_config/mih_theme.dart';
@@ -66,19 +79,66 @@ class _MzansiInnovationHubState extends State<MzansiInnovationHub> {
double width = MediaQuery.sizeOf(context).width;
theme.setScreenType(width);
precacheImage(theme.loadingImage(), context);
return MaterialApp.router(
title: getTitle(),
themeMode: ThemeMode.dark,
theme: theme.getThemeData(),
darkTheme: theme.getThemeData(),
debugShowCheckedModeBanner: false,
routerConfig: widget.router,
builder: (context, child) {
return UpgradeAlert(
navigatorKey: widget.router.routerDelegate.navigatorKey,
child: child ?? const Text('Upgrade Alert'),
);
},
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => MihAuthenticationProvider(),
),
ChangeNotifierProvider(
create: (context) => MzansiProfileProvider(),
),
ChangeNotifierProvider(
create: (context) => MzansiWalletProvider(),
),
ChangeNotifierProvider(
create: (context) => MzansiAiProvider(),
),
ChangeNotifierProvider(
create: (context) => MzansiDirectoryProvider(),
),
ChangeNotifierProvider(
create: (context) => MihBannerAdProvider(),
),
ChangeNotifierProvider(
create: (context) => MihCalculatorProvider(),
),
ChangeNotifierProvider(
create: (context) => MihAccessControllsProvider(),
),
ChangeNotifierProvider(
create: (context) => MihCalendarProvider(),
),
ChangeNotifierProvider(
create: (context) => AboutMihProvider(),
),
ChangeNotifierProvider(
create: (context) => MihMineSweeperProvider(),
),
ChangeNotifierProvider(
create: (context) => PatientManagerProvider(),
),
],
child: MaterialApp.router(
title: getTitle(),
themeMode: ThemeMode.dark,
theme: theme.getThemeData(),
darkTheme: theme.getThemeData(),
debugShowCheckedModeBanner: false,
routerConfig: widget.router,
builder: (context, child) {
if (child == null) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
return UpgradeAlert(
navigatorKey: widget.router.routerDelegate.navigatorKey,
child: child,
);
},
),
);
}
}

View File

@@ -20,6 +20,12 @@ void main() async {
apiBasePath: "/auth",
);
if (!kIsWeb) {
const List<String> testDeviceIds = ['733d4c68-9b54-453a-9622-2df407310f40'];
MobileAds.instance.updateRequestConfiguration(
RequestConfiguration(
testDeviceIds: testDeviceIds,
),
);
MobileAds.instance.initialize();
} else {
usePathUrlStrategy();
@@ -29,5 +35,7 @@ void main() async {
});
final GoRouter appRouter = MihGoRouter().mihRouter;
FlutterNativeSplash.remove();
runApp(MzansiInnovationHub(router: appRouter,));
runApp(MzansiInnovationHub(
router: appRouter,
));
}

View File

@@ -0,0 +1,42 @@
class MinesweeperPlayerScore {
String app_id;
String username;
String proPicUrl;
String difficulty;
String game_time;
double game_score;
DateTime played_date;
MinesweeperPlayerScore({
required this.app_id,
required this.username,
required this.proPicUrl,
required this.difficulty,
required this.game_time,
required this.game_score,
required this.played_date,
});
factory MinesweeperPlayerScore.fromJson(Map<String, dynamic> json) {
return MinesweeperPlayerScore(
app_id: json['app_id'],
username: json['username'],
proPicUrl: json['proPicUrl'],
difficulty: json['difficulty'],
game_time: json['game_time'],
game_score: json['game_score'],
played_date: DateTime.parse(json['played_date']),
);
}
Map<String, dynamic> toJson() {
return {
'app_id': app_id,
'username': username,
'proPicUrl': proPicUrl,
'difficulty': difficulty,
'game_time': game_score,
'played_date': played_date.toIso8601String(),
};
}
}

View File

@@ -396,7 +396,6 @@ class _PackageToolOneState extends State<PackageToolOne> {
return widget.business != null
? MihBusinessProfilePreview(
business: widget.business!,
myLocation: myLocation,
)
: Text("NoBusiness Data");
}
@@ -424,7 +423,7 @@ class _PackageToolOneState extends State<PackageToolOne> {
"rating",
"mission_vision",
),
startUpSearch: '',
// startUpSearch: '',
width: 300,
).redacted(
context: context,

View File

@@ -1,10 +1,10 @@
@font-face {
font-family: 'Mih_Icons';
src: url('fonts/Mih_Icons.eot?blbuxz');
src: url('fonts/Mih_Icons.eot?blbuxz#iefix') format('embedded-opentype'),
url('fonts/Mih_Icons.ttf?blbuxz') format('truetype'),
url('fonts/Mih_Icons.woff?blbuxz') format('woff'),
url('fonts/Mih_Icons.svg?blbuxz#Mih_Icons') format('svg');
font-family: 'icomoon';
src: url('fonts/icomoon.eot?8flwgj');
src: url('fonts/icomoon.eot?8flwgj#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?8flwgj') format('truetype'),
url('fonts/icomoon.woff?8flwgj') format('woff'),
url('fonts/icomoon.svg?8flwgj#icomoon') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
@@ -13,7 +13,7 @@
[class^="icon-"],
[class*=" icon-"] {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'Mih_Icons' !important;
font-family: 'icomoon' !important;
/* speak: never; */
font-style: normal;
font-weight: normal;
@@ -26,70 +26,74 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-mzansi_directory:before {
.icon-mine_sweeper:before {
content: "\e900";
}
.icon-personal_profile:before {
.icon-mzansi_directory:before {
content: "\e901";
}
.icon-about_mih:before {
.icon-personal_profile:before {
content: "\e902";
}
.icon-access_control:before {
.icon-about_mih:before {
content: "\e903";
}
.icon-business_profile:before {
.icon-access_control:before {
content: "\e904";
}
.icon-business_setup:before {
.icon-business_profile:before {
content: "\e905";
}
.icon-i_dont_know:before {
.icon-business_setup:before {
content: "\e906";
}
.icon-mih_logo:before {
.icon-calculator:before {
content: "\e907";
}
.icon-mih_ring:before {
.icon-calendar:before {
content: "\e908";
}
.icon-mzansi_ai:before {
.icon-i_dont_know:before {
content: "\e909";
}
.icon-mzansi_wallet:before {
.icon-mih_logo:before {
content: "\e90a";
}
.icon-notifications:before {
.icon-mih_ring:before {
content: "\e90b";
}
.icon-patient_manager:before {
.icon-mzansi_ai:before {
content: "\e90c";
}
.icon-patient_profile:before {
.icon-mzansi_wallet:before {
content: "\e90d";
}
.icon-profile_setup:before {
.icon-notifications:before {
content: "\e90e";
}
.icon-calculator:before {
content: "\e940";
.icon-patient_manager:before {
content: "\e90f";
}
.icon-calendar:before {
content: "\e953";
.icon-patient_profile:before {
content: "\e910";
}
.icon-profile_setup:before {
content: "\e911";
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:provider/provider.dart';
class MihBannerAd extends StatefulWidget {
const MihBannerAd({super.key});
@@ -10,66 +12,26 @@ class MihBannerAd extends StatefulWidget {
}
class _MihBannerAdState extends State<MihBannerAd> {
BannerAd? _bannerAd;
bool _isBannerAdLoaded = false;
final adUnitId = AppEnviroment.bannerAdUnitId;
String errorMessage = '';
void _loadBannerAd() {
_bannerAd = BannerAd(
adUnitId: adUnitId,
request: const AdRequest(),
size: AdSize.banner,
listener: BannerAdListener(
onAdLoaded: (ad) {
debugPrint('$ad loaded.');
setState(() {
_isBannerAdLoaded = true;
});
},
onAdFailedToLoad: (ad, err) {
debugPrint('BannerAd failed to load: $err');
setState(() {
errorMessage =
'Failed to load ad- Message: ${err.message} Code :${err.code}';
});
ad.dispose(); // Dispose the ad to free resources
},
onAdOpened: (Ad ad) => debugPrint('$ad opened.'),
onAdClosed: (Ad ad) => debugPrint('$ad closed.'),
onAdImpression: (Ad ad) => debugPrint('$ad impression.'),
),
);
_bannerAd!.load();
}
@override
void dispose() {
_bannerAd?.dispose(); // Dispose the ad when the widget is removed
super.dispose();
}
@override
void initState() {
super.initState();
_loadBannerAd();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
_bannerAd != null && _isBannerAdLoaded
? SizedBox(
width: _bannerAd!.size.width.toDouble(),
height: _bannerAd!.size.height.toDouble(),
child: AdWidget(ad: _bannerAd!))
: SizedBox(
child:
Text(AppEnviroment.getEnv() == "Dev" ? errorMessage : ""),
),
],
return Consumer<MihBannerAdProvider>(
builder: (context, bannerAdProvider, child) {
return Column(
children: [
bannerAdProvider.bannerAd != null &&
bannerAdProvider.isBannerAdLoaded
? SizedBox(
width: bannerAdProvider.bannerAd!.size.width.toDouble(),
height: bannerAdProvider.bannerAd!.size.height.toDouble(),
child: AdWidget(ad: bannerAdProvider.bannerAd!))
: SizedBox(
child: Text(AppEnviroment.getEnv() == "Dev"
? bannerAdProvider.errorMessage
: ""),
),
],
);
},
);
}
}

View File

@@ -4,17 +4,17 @@ import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/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_services/mih_location_services.dart';
import 'package:provider/provider.dart';
class MihBusinessProfilePreview extends StatefulWidget {
final Business business;
final String? myLocation;
const MihBusinessProfilePreview({
super.key,
required this.business,
required this.myLocation,
});
@override
@@ -26,10 +26,10 @@ class _MihBusinessProfilePreviewState extends State<MihBusinessProfilePreview> {
late Future<String> futureImageUrl;
PlatformFile? file;
String calculateDistance() {
String calculateDistance(MzansiDirectoryProvider directoryProvider) {
try {
double distanceInKm = MIHLocationAPI().getDistanceInMeaters(
widget.myLocation!, widget.business.gps_location) /
directoryProvider.userLocation, widget.business.gps_location) /
1000;
return "${distanceInKm.toStringAsFixed(2)} km";
} catch (error) {
@@ -48,73 +48,82 @@ class _MihBusinessProfilePreviewState extends State<MihBusinessProfilePreview> {
@override
Widget build(BuildContext context) {
double profilePictureWidth = 60;
return Row(
children: [
FutureBuilder(
future: futureImageUrl,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState == ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "") {
return MihCircleAvatar(
imageFile: NetworkImage(asyncSnapshot.requireData),
width: profilePictureWidth,
editable: false,
fileNameController: TextEditingController(),
userSelectedfile: file,
frameColor: 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"),
);
}
}),
const SizedBox(width: 15),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
return Consumer<MzansiDirectoryProvider>(
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
Widget? child) {
return Row(
children: [
Text(
widget.business.Name,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
Text(
widget.business.type,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
Text(
widget.myLocation != null || widget.myLocation!.isEmpty
? calculateDistance()
: "0.00 km",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 10,
),
),
FutureBuilder(
future: futureImageUrl,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState == ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "") {
return MihCircleAvatar(
imageFile: NetworkImage(asyncSnapshot.requireData),
width: profilePictureWidth,
editable: false,
fileNameController: TextEditingController(),
userSelectedfile: file,
frameColor: MihColors.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"),
);
}
}),
const SizedBox(width: 15),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.business.Name,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
Text(
widget.business.type,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 15,
),
),
Text(
directoryProvider.userPosition != null
? calculateDistance(directoryProvider)
: "0.00 km",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 10,
),
),
],
)
],
)
],
);
},
);
}
}

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
class MihButton extends StatelessWidget {
final void Function()? onPressed;
final void Function()? onLongPressed;
final Color buttonColor;
final double? width;
final double? height;
@@ -12,6 +13,7 @@ class MihButton extends StatelessWidget {
const MihButton({
super.key,
required this.onPressed,
this.onLongPressed,
required this.buttonColor,
this.width,
this.height,
@@ -49,6 +51,7 @@ class MihButton extends StatelessWidget {
highlightColor: rippleColor.withValues(alpha: 0.2),
hoverColor: rippleColor.withValues(alpha: 0.3),
onTap: onPressed,
onLongPress: onLongPressed,
child: Container(
width: width,
height: height,

View File

@@ -1,6 +1,9 @@
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_components/mih_providers/mih_calendar_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:provider/provider.dart';
import 'package:table_calendar/table_calendar.dart';
class MIHCalendar extends StatefulWidget {
@@ -19,16 +22,29 @@ class MIHCalendar extends StatefulWidget {
}
class _MIHCalendarState extends State<MIHCalendar> {
DateTime selectedDay = DateTime.now();
late DateTime selectedDay;
CalendarFormat _calendarFormat = CalendarFormat.week;
void onDaySelected(DateTime day, DateTime focusedDay) {
KenLogger.success("Selected Day: $day");
setState(() {
selectedDay = day;
});
widget.setDate(selectedDay.toString().split(" ")[0]);
}
@override
void initState() {
super.initState();
MihCalendarProvider mihCalendarProvider =
context.read<MihCalendarProvider>();
if (mihCalendarProvider.selectedDay.isNotEmpty) {
selectedDay = DateTime.parse(mihCalendarProvider.selectedDay);
} else {
selectedDay = DateTime.now();
}
}
@override
Widget build(BuildContext context) {
return SizedBox(

View File

@@ -10,7 +10,7 @@ class MihCircleAvatar extends StatefulWidget {
final ImageProvider<Object>? imageFile;
final double width;
final bool editable;
final TextEditingController fileNameController;
final TextEditingController? fileNameController;
final onChange;
final PlatformFile? userSelectedfile;
final Color frameColor;
@@ -130,7 +130,7 @@ class _MihCircleAvatarState extends State<MihCircleAvatar> {
});
setState(() {
widget.fileNameController.text = selectedFile.name;
widget.fileNameController!.text = selectedFile.name;
});
} else {
if (result != null) {
@@ -148,7 +148,7 @@ class _MihCircleAvatarState extends State<MihCircleAvatar> {
});
setState(() {
widget.fileNameController.text =
widget.fileNameController!.text =
file.path.split('/').last;
});
} else {
@@ -157,7 +157,7 @@ class _MihCircleAvatarState extends State<MihCircleAvatar> {
}
}
} catch (e) {
print("Error: $e");
print("Here Error: $e");
}
},
icon: Icon(

View File

@@ -10,6 +10,7 @@ class MihDropdownField extends StatefulWidget {
final bool editable;
final bool enableSearch;
final FormFieldValidator<String>? validator;
final Function(String?)? onSelected;
const MihDropdownField({
super.key,
@@ -20,6 +21,7 @@ class MihDropdownField extends StatefulWidget {
required this.editable,
required this.enableSearch,
this.validator,
this.onSelected,
});
@override
@@ -117,8 +119,10 @@ class _MihDropdownFieldState extends State<MihDropdownField> {
enableSearch: widget.enableSearch,
enableFilter: widget.enableSearch,
enabled: widget.editable,
textInputAction: TextInputAction.search,
requestFocusOnTap: true,
textInputAction: widget.enableSearch
? TextInputAction.search
: TextInputAction.none,
requestFocusOnTap: widget.enableSearch,
menuHeight: 400,
expandedInsets: EdgeInsets.zero,
textStyle: TextStyle(
@@ -153,6 +157,7 @@ class _MihDropdownFieldState extends State<MihDropdownField> {
),
onSelected: (String? selectedValue) {
field.didChange(selectedValue);
widget.onSelected?.call(selectedValue);
},
menuStyle: MenuStyle(
backgroundColor: WidgetStatePropertyAll(

View File

@@ -11,54 +11,57 @@ class MihIcons {
// IconData constants based on your style.css file
// Note: We convert the hex code from CSS (\eXXX) to an integer (0xeXXX)
static const IconData mzansiDirectory =
static const IconData mineSweeper =
IconData(0xe900, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData personalProfile =
static const IconData mzansiDirectory =
IconData(0xe901, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData aboutMih =
static const IconData personalProfile =
IconData(0xe902, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData accessControl =
static const IconData aboutMih =
IconData(0xe903, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData businessProfile =
static const IconData accessControl =
IconData(0xe904, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData businessSetup =
static const IconData businessProfile =
IconData(0xe905, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData iDontKnow =
static const IconData businessSetup =
IconData(0xe906, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData mihLogo =
static const IconData calculator =
IconData(0xe907, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData mihRing =
static const IconData calendar =
IconData(0xe908, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData mzansiAi =
static const IconData iDontKnow =
IconData(0xe909, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData mzansiWallet =
static const IconData mihLogo =
IconData(0xe90a, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData notifications =
static const IconData mihRing =
IconData(0xe90b, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData patientManager =
static const IconData mzansiAi =
IconData(0xe90c, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData patientProfile =
static const IconData mzansiWallet =
IconData(0xe90d, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData profileSetup =
static const IconData notifications =
IconData(0xe90e, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData calculator =
IconData(0xe940, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData patientManager =
IconData(0xe90f, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData calendar =
IconData(0xe953, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData patientProfile =
IconData(0xe910, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
static const IconData profileSetup =
IconData(0xe911, fontFamily: _mihFontFam, fontPackage: _mihFontPkg);
}

View File

@@ -2,6 +2,7 @@ import 'dart:io';
import 'package:file_picker/file_picker.dart';
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_config/mih_colors.dart';
@@ -32,19 +33,9 @@ class _MihImageDisplayState extends State<MihImageDisplay> {
late ImageProvider<Object>? imagePreview;
ImageProvider<Object>? getImage() {
Color dark = const Color(0XFF3A4454);
KenLogger.success(widget.imageFile.toString());
if (widget.imageFile == null) {
if (MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark") ==
dark) {
print("here in light icon");
return const AssetImage(
'lib/mih_components/mih_package_components/assets/images/i-dont-know-dark.png');
} else {
print("here in dark icon");
return const AssetImage(
'lib/mih_components/mih_package_components/assets/images/i-dont-know-light.png');
}
return null;
} else {
return widget.imageFile;
}
@@ -69,10 +60,26 @@ class _MihImageDisplayState extends State<MihImageDisplay> {
child: Stack(
alignment: Alignment.center,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(widget.width * 0.1),
child: Image(image: imagePreview!),
),
imagePreview != null
? ClipRRect(
borderRadius: BorderRadius.circular(widget.width * 0.1),
child: Image(image: imagePreview!),
)
: Container(
width: widget.width,
height: widget.height,
decoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(widget.width * 0.1),
),
child: Icon(
Icons.image_not_supported_rounded,
size: widget.width * 0.3,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
Visibility(
visible: widget.editable,
child: Positioned(
@@ -133,7 +140,7 @@ class _MihImageDisplayState extends State<MihImageDisplay> {
}
}
} catch (e) {
print("Error: $e");
print("here 2 Error: $e");
}
},
icon: const Icon(

View File

@@ -35,7 +35,7 @@ class _MihPackageAlertState extends State<MihPackageAlert> {
setState(() {
popUpWidth = (size!.width / 4) * 2;
popUpheight = null;
popUpTitleSize = 25.0;
popUpTitleSize = 30.0;
popUpSubtitleSize = 20.0;
popUpBodySize = 15;
popUpPaddingSize = 25.0;
@@ -45,7 +45,7 @@ class _MihPackageAlertState extends State<MihPackageAlert> {
setState(() {
popUpWidth = size!.width - (size!.width * 0.1);
popUpheight = null;
popUpTitleSize = 20.0;
popUpTitleSize = 25.0;
popUpSubtitleSize = 18.0;
popUpBodySize = 15;
popUpPaddingSize = 15.0;

View File

@@ -191,18 +191,21 @@ class _MihTextFormFieldState extends State<MihTextFormField> {
),
decoration: InputDecoration(
suffixIcon: widget.passwordMode == true
? IconButton(
icon: Icon(
_obscureText
? Icons.visibility_off
: Icons.visibility,
color: widget.inputColor,
? FocusScope(
canRequestFocus: false,
child: IconButton(
icon: Icon(
_obscureText
? Icons.visibility_off
: Icons.visibility,
color: widget.inputColor,
),
onPressed: () {
setState(() {
_obscureText = !_obscureText;
});
},
),
onPressed: () {
setState(() {
_obscureText = !_obscureText;
});
},
)
: null,
errorStyle: const TextStyle(

View File

@@ -0,0 +1,19 @@
import 'package:flutter/foundation.dart';
class AboutMihProvider extends ChangeNotifier {
int toolIndex;
AboutMihProvider({
this.toolIndex = 0,
});
void reset() {
toolIndex = 0;
notifyListeners();
}
void setToolIndex(int index) {
toolIndex = index;
notifyListeners();
}
}

View File

@@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart';
class MihAccessControllsProvider extends ChangeNotifier {
int toolIndex;
List<PatientAccess>? accessList;
MihAccessControllsProvider({
this.toolIndex = 0,
});
void reset() {
toolIndex = 0;
accessList = null;
notifyListeners();
}
void setToolIndex(int index) {
toolIndex = index;
}
void setAccessList(List<PatientAccess> accesses) {
accessList = accesses;
notifyListeners();
}
void editAccessItem(PatientAccess updatedAccess) {
if (accessList == null) return;
int index = accessList!.indexWhere((access) =>
access.app_id == updatedAccess.app_id &&
access.business_id == updatedAccess.business_id);
if (index != -1) {
accessList![index] = updatedAccess;
notifyListeners();
}
}
}

View File

@@ -0,0 +1,19 @@
import 'package:flutter/foundation.dart';
class MihAuthenticationProvider extends ChangeNotifier {
int toolIndex;
MihAuthenticationProvider({
this.toolIndex = 0,
});
void reset() {
toolIndex = 0;
notifyListeners();
}
void setToolIndex(int index) {
toolIndex = index;
notifyListeners();
}
}

View File

@@ -0,0 +1,57 @@
import 'package:flutter/foundation.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
class MihBannerAdProvider extends ChangeNotifier {
BannerAd? bannerAd;
final adUnitId = AppEnviroment.bannerAdUnitId;
bool isBannerAdLoaded = false;
String errorMessage = '';
MihBannerAdProvider({
this.bannerAd,
this.isBannerAdLoaded = false,
this.errorMessage = '',
});
void reset() {
bannerAd = null;
isBannerAdLoaded = false;
errorMessage = "";
notifyListeners();
}
@override
void dispose() {
bannerAd?.dispose();
super.dispose();
}
void loadBannerAd() {
bannerAd = BannerAd(
adUnitId: adUnitId,
request: const AdRequest(),
size: AdSize.banner,
listener: BannerAdListener(
onAdLoaded: (ad) {
debugPrint('$ad loaded.');
isBannerAdLoaded = true;
notifyListeners();
},
onAdFailedToLoad: (ad, err) {
debugPrint('BannerAd failed to load: $err');
errorMessage =
'Failed to load ad- Message: ${err.message} Code :${err.code}';
ad.dispose(); // Dispose the ad to free resources
isBannerAdLoaded = false; // ⬅️ Explicitly set to false
bannerAd = null; // ⬅️ Explicitly set to null
notifyListeners();
},
onAdOpened: (Ad ad) => debugPrint('$ad opened.'),
onAdClosed: (Ad ad) => debugPrint('$ad closed.'),
onAdImpression: (Ad ad) => debugPrint('$ad impression.'),
),
);
bannerAd!.load();
}
}

View File

@@ -0,0 +1,27 @@
import 'package:flutter/foundation.dart';
class MihCalculatorProvider extends ChangeNotifier {
List<String> availableCurrencies;
int toolIndex;
MihCalculatorProvider({
this.availableCurrencies = const [],
this.toolIndex = 0,
});
void reset() {
availableCurrencies = [];
toolIndex = 0;
notifyListeners();
}
void setToolIndex(int index) {
toolIndex = index;
notifyListeners();
}
void setAvailableCurrencies({required List<String> currencies}) async {
availableCurrencies = currencies;
notifyListeners();
}
}

View File

@@ -0,0 +1,87 @@
import 'package:flutter/foundation.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/appointment.dart';
class MihCalendarProvider extends ChangeNotifier {
int toolIndex;
String selectedDay = DateTime.now().toString().split(" ")[0];
List<Appointment>? personalAppointments;
List<Appointment>? businessAppointments;
MihCalendarProvider({
this.toolIndex = 0,
});
void reset() {
toolIndex = 0;
personalAppointments = null;
businessAppointments = null;
notifyListeners();
}
void setToolIndex(int index) {
toolIndex = index;
notifyListeners();
}
void setSelectedDay(String day) {
selectedDay = day;
notifyListeners();
}
void resetSelectedDay() {
selectedDay = DateTime.now().toString().split(" ")[0];
notifyListeners();
}
void setPersonalAppointments({required List<Appointment> appointments}) {
personalAppointments = appointments;
notifyListeners();
}
void setBusinessAppointments({required List<Appointment> appointments}) {
businessAppointments = appointments;
notifyListeners();
}
void addPersonalAppointment({required Appointment newAppointment}) {
personalAppointments?.add(newAppointment);
notifyListeners();
}
void addBusinessAppointment({required Appointment newAppointment}) {
businessAppointments?.add(newAppointment);
notifyListeners();
}
void editPersonalAppointment({required Appointment updatedAppointment}) {
int index = personalAppointments?.indexWhere((appointment) =>
appointment.idappointments == updatedAppointment.idappointments) ??
-1;
if (index != -1) {
personalAppointments?[index] = updatedAppointment;
notifyListeners();
}
}
void editBusinessAppointment({required Appointment updatedAppointment}) {
int index = businessAppointments?.indexWhere((appointment) =>
appointment.idappointments == updatedAppointment.idappointments) ??
-1;
if (index != -1) {
businessAppointments?[index] = updatedAppointment;
notifyListeners();
}
}
void deletePersonalAppointment({required int appointmentId}) {
personalAppointments?.removeWhere(
(appointment) => appointment.idappointments == appointmentId);
notifyListeners();
}
void deleteBusinessAppointment({required int appointmentId}) {
businessAppointments?.removeWhere(
(appointment) => appointment.idappointments == appointmentId);
notifyListeners();
}
}

View File

@@ -0,0 +1,81 @@
import 'package:flutter/widgets.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/minesweeper_player_score.dart';
class MihMineSweeperProvider extends ChangeNotifier {
String difficulty;
int toolIndex;
int rowCount;
int columnCount;
int totalMines;
List<MinesweeperPlayerScore>? leaderboard;
List<MinesweeperPlayerScore>? myScoreboard;
List<ImageProvider<Object>?> leaderboardUserPictures = [];
MihMineSweeperProvider({
this.difficulty = "Easy",
this.toolIndex = 0,
this.rowCount = 10,
this.columnCount = 10,
this.totalMines = 15,
});
void reset() {
difficulty = "Easy";
toolIndex = 0;
rowCount = 10;
columnCount = 10;
totalMines = 15;
notifyListeners();
}
void setDifficulty(String difficulty) {
this.difficulty = difficulty;
notifyListeners();
}
void setToolIndex(int index) {
toolIndex = index;
notifyListeners();
}
void setRowCount(int rowCount) {
this.rowCount = rowCount;
notifyListeners();
}
void setCoulmnCount(int columnCount) {
this.columnCount = columnCount;
notifyListeners();
}
void setTotalMines(int totalMines) {
this.totalMines = totalMines;
notifyListeners();
}
void setLeaderboard({required List<MinesweeperPlayerScore>? leaderboard}) {
if (leaderboard == null) {
this.leaderboard = [];
} else {
this.leaderboard = leaderboard;
}
notifyListeners();
}
void setMyScoreboard({
required List<MinesweeperPlayerScore>? myScoreboard,
}) {
if (myScoreboard == null) {
this.myScoreboard = [];
} else {
this.myScoreboard = myScoreboard;
}
notifyListeners();
}
void setLeaderboardUserPictures(
{required List<ImageProvider<Object>?> leaderboardUserPictures}) {
this.leaderboardUserPictures = leaderboardUserPictures;
notifyListeners();
}
}

View File

@@ -0,0 +1,26 @@
import 'package:flutter/material.dart';
class MzansiAiProvider extends ChangeNotifier {
int toolIndex;
String? startUpQuestion;
MzansiAiProvider({
this.toolIndex = 0,
});
void reset() {
toolIndex = 0;
startUpQuestion = null;
notifyListeners();
}
void setToolIndex(int index) {
toolIndex = index;
notifyListeners();
}
void setStartUpQuestion(String? question) {
startUpQuestion = question;
notifyListeners();
}
}

View File

@@ -0,0 +1,104 @@
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
class MzansiDirectoryProvider extends ChangeNotifier {
int toolIndex;
Position? userPosition;
String userLocation;
bool personalSearch;
List<BookmarkedBusiness> bookmarkedBusinesses = [];
Map<String, Business?> businessDetailsMap = {};
List<Business>? searchedBusinesses;
Business? selectedBusiness;
List<AppUser>? searchedUsers;
AppUser? selectedUser;
String searchTerm;
String businessTypeFilter;
MzansiDirectoryProvider({
this.toolIndex = 0,
this.personalSearch = true,
this.userLocation = "Unknown Location",
this.searchTerm = "",
this.businessTypeFilter = "",
});
void reset() {
toolIndex = 0;
userPosition = null;
userLocation = "Unknown Location";
personalSearch = true;
bookmarkedBusinesses = [];
businessDetailsMap = {};
searchedBusinesses = null;
selectedBusiness = null;
searchedUsers = null;
selectedUser = null;
searchTerm = "";
businessTypeFilter = "";
notifyListeners();
}
void setToolIndex(int index) {
toolIndex = index;
notifyListeners();
}
void setUserPosition(Position? position) {
userPosition = position;
if (position == null) {
userLocation = "Unknown Location";
} else {
userLocation = "${position.latitude}, ${position.longitude}";
}
notifyListeners();
}
void setPersonalSearch(bool personal) {
personalSearch = personal;
notifyListeners();
}
void setFavouriteBusinesses({required List<BookmarkedBusiness> businesses}) {
bookmarkedBusinesses = businesses;
notifyListeners();
}
void setBusinessDetailsMap({required Map<String, Business?> detailsMap}) {
businessDetailsMap = detailsMap;
notifyListeners();
}
void setSearchedBusinesses({required List<Business> searchedBusinesses}) {
this.searchedBusinesses = searchedBusinesses;
notifyListeners();
}
void setSelectedBusiness({required Business business}) {
selectedBusiness = business;
notifyListeners();
}
void setSearchedUsers({required List<AppUser> searchedUsers}) {
this.searchedUsers = searchedUsers;
notifyListeners();
}
void setSelectedUser({required AppUser user}) {
selectedUser = user;
notifyListeners();
}
void setSearchTerm({required String searchTerm}) {
this.searchTerm = searchTerm;
notifyListeners();
}
void setBusinessTypeFilter({required String businessTypeFilter}) {
this.businessTypeFilter = businessTypeFilter;
notifyListeners();
}
}

View File

@@ -0,0 +1,141 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/user_consent.dart';
class MzansiProfileProvider extends ChangeNotifier {
bool personalHome;
int personalIndex;
int businessIndex;
AppUser? user;
String? userProfilePicUrl;
ImageProvider<Object>? userProfilePicture;
Business? business;
String? businessProfilePicUrl;
ImageProvider<Object>? businessProfilePicture;
BusinessUser? businessUser;
String? businessUserSignatureUrl;
ImageProvider<Object>? businessUserSignature;
UserConsent? userConsent;
List<BusinessEmployee>? employeeList;
List<AppUser> userSearchResults = [];
MzansiProfileProvider({
this.personalHome = true,
this.personalIndex = 0,
this.businessIndex = 0,
});
void reset() {
personalHome = true;
personalIndex = 0;
businessIndex = 0;
user = null;
userProfilePicUrl = null;
userProfilePicture = null;
business = null;
businessProfilePicUrl = null;
businessProfilePicture = null;
businessUser = null;
businessUserSignatureUrl = null;
businessUserSignature = null;
userConsent = null;
notifyListeners();
}
void setPersonalHome(bool isPersonalHome) {
personalHome = isPersonalHome;
notifyListeners();
}
void setPersonalIndex(int index) {
personalIndex = index;
notifyListeners();
}
void setBusinessIndex(int index) {
businessIndex = index;
notifyListeners();
}
void setUser({
required AppUser newUser,
}) {
user = newUser;
notifyListeners();
}
void setUserProfilePicUrl(String url) {
userProfilePicUrl = url;
userProfilePicture = url.isNotEmpty ? NetworkImage(url) : null;
notifyListeners();
}
void setBusiness({
Business? newBusiness,
}) {
business = newBusiness;
notifyListeners();
}
void setBusinessProfilePicUrl(String url) {
businessProfilePicUrl = url;
businessProfilePicture = url.isNotEmpty ? NetworkImage(url) : null;
notifyListeners();
}
void setBusinessUser({required BusinessUser newBusinessUser}) {
businessUser = newBusinessUser;
notifyListeners();
}
void setBusinessUserSignatureUrl(String url) {
businessUserSignatureUrl = url;
businessUserSignature = url.isNotEmpty ? NetworkImage(url) : null;
notifyListeners();
}
void setUserConsent(UserConsent? newUserConsent) {
userConsent = newUserConsent;
notifyListeners();
}
void setEmployeeList({required List<BusinessEmployee> employeeList}) {
this.employeeList = employeeList;
notifyListeners();
}
void addLoyaltyCard({required BusinessEmployee newEmployee}) {
employeeList!.add(newEmployee);
notifyListeners();
}
void updateEmplyeeDetails({required BusinessEmployee updatedEmployee}) {
int index = employeeList!.indexWhere((employee) =>
employee.business_id == updatedEmployee.business_id &&
employee.app_id == updatedEmployee.app_id);
if (index != -1) {
employeeList![index] = updatedEmployee;
notifyListeners();
}
}
void deleteEmplyee({required BusinessEmployee deletedEmployee}) {
employeeList!.removeWhere((employee) =>
employee.business_id == deletedEmployee.business_id &&
employee.app_id == deletedEmployee.app_id);
notifyListeners();
}
void addEmployee({required BusinessEmployee newEmployee}) {
employeeList!.add(newEmployee);
notifyListeners();
}
void setUserearchResults({required List<AppUser> userSearchResults}) {
this.userSearchResults = userSearchResults;
notifyListeners();
}
}

View File

@@ -0,0 +1,54 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/loyalty_card.dart';
class MzansiWalletProvider extends ChangeNotifier {
List<MIHLoyaltyCard> loyaltyCards;
List<MIHLoyaltyCard> favouriteCards;
int toolIndex;
MzansiWalletProvider({
this.loyaltyCards = const [],
this.favouriteCards = const [],
this.toolIndex = 0,
});
void reset() {
toolIndex = 0;
loyaltyCards = [];
favouriteCards = [];
}
void setToolIndex(int index) {
toolIndex = index;
notifyListeners();
}
void setLoyaltyCards({required List<MIHLoyaltyCard> cards}) async {
loyaltyCards = cards;
notifyListeners();
}
void setFavouriteCards({required List<MIHLoyaltyCard> cards}) async {
favouriteCards = cards;
notifyListeners();
}
void addLoyaltyCard({required MIHLoyaltyCard newCard}) {
loyaltyCards.add(newCard);
notifyListeners();
}
void deleteLoyaltyCard({required int cardId}) {
loyaltyCards.removeWhere((card) => card.idloyalty_cards == cardId);
notifyListeners();
}
void editLoyaltyCard({required MIHLoyaltyCard updatedCard}) {
int index = loyaltyCards.indexWhere(
(card) => card.idloyalty_cards == updatedCard.idloyalty_cards);
if (index != -1) {
loyaltyCards[index] = updatedCard;
notifyListeners();
}
}
}

View File

@@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/claim_statement_file.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/files.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/notes.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patients.dart';
class PatientManagerProvider extends ChangeNotifier {
int patientProfileIndex;
int patientManagerIndex;
int fileViewerIndex;
bool personalMode;
List<PatientAccess>? myPaitentList;
Patient? selectedPatient;
List<Note>? consultationNotes;
List<PFile>? patientDocuments;
List<ClaimStatementFile>? patientClaimsDocuments;
List<Patient> patientSearchResults = [];
PatientManagerProvider({
this.patientProfileIndex = 0,
this.patientManagerIndex = 0,
this.fileViewerIndex = 0,
this.personalMode = true,
});
void reset() {
patientProfileIndex = 0;
patientManagerIndex = 0;
personalMode = true;
selectedPatient = null;
}
void setPatientProfileIndex(int index) {
patientProfileIndex = index;
notifyListeners();
}
void setPatientManagerIndex(int index) {
patientManagerIndex = index;
notifyListeners();
}
void setFileViewerIndex(int index) {
patientProfileIndex = index;
notifyListeners();
}
void setPersonalMode(bool personalMode) {
this.personalMode = personalMode;
notifyListeners();
}
void setSelectedPatient({required Patient? selectedPatient}) {
this.selectedPatient = selectedPatient;
notifyListeners();
}
void setMyPatientList({required List<PatientAccess>? myPaitentList}) {
this.myPaitentList = myPaitentList ?? [];
notifyListeners();
}
void setConsultationNotes({required List<Note>? consultationNotes}) {
this.consultationNotes = consultationNotes ?? [];
notifyListeners();
}
void setPatientDocuments({required List<PFile>? patientDocuments}) {
this.patientDocuments = patientDocuments ?? [];
notifyListeners();
}
void setClaimsDocuments(
{required List<ClaimStatementFile>? patientClaimsDocuments}) {
this.patientClaimsDocuments = patientClaimsDocuments ?? [];
notifyListeners();
}
void setPatientSearchResults({required List<Patient> patientSearchResults}) {
this.patientSearchResults = patientSearchResults;
notifyListeners();
}
}

View File

@@ -37,7 +37,7 @@ class MihColors {
if (darkMode == true) {
return const Color(0xff8ae290);
} else {
return const Color(0xffB0F2B4);
return const Color(0xFF41B349);
}
}
@@ -63,7 +63,7 @@ class MihColors {
return const Color(0xffd69d7d);
} else {
// Add a different shade of pink for light mode
return const Color(0xffd69d7d);
return const Color(0xFFBD7145);
}
}
@@ -81,7 +81,7 @@ class MihColors {
return const Color(0xff6e7dcc);
} else {
// Add a different shade of pink for light mode
return const Color(0xff6e7dcc);
return const Color(0xFF5567C0);
}
}
@@ -90,7 +90,34 @@ class MihColors {
return const Color(0xffb682e7);
} else {
// Add a different shade of pink for light mode
return const Color(0xffb682e7);
return const Color(0xFF9857D4);
}
}
static Color getGoldColor(bool darkMode) {
if (darkMode == true) {
return const Color(0xFFD4AF37);
} else {
// Add a different shade of pink for light mode
return const Color(0xffFFD700);
}
}
static Color getSilverColor(bool darkMode) {
if (darkMode == true) {
return const Color(0xffC0C0C0);
} else {
// Add a different shade of pink for light mode
return const Color(0xFFA6A6A6);
}
}
static Color getBronze(bool darkMode) {
if (darkMode == true) {
return const Color(0xffB1560F);
} else {
// Add a different shade of pink for light mode
return const Color(0xFFCD7F32);
}
}
}

View File

@@ -1,9 +1,10 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_print_prevew.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/Example/package_test.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_packages/about_mih/about_mih.dart';
import 'package:mzansi_innovation_hub/mih_packages/access_review/mih_access.dart';
import 'package:mzansi_innovation_hub/mih_packages/calculator/mih_calculator.dart';
@@ -13,21 +14,22 @@ import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/mih_auth_p
import 'package:mzansi_innovation_hub/mih_packages/mih_authentication/mih_authentication.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_home/mih_home.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_home/mih_route_error.dart';
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/mih_mine_sweeper.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/mzansi_ai.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/mzansi_directory.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/mzansi_business_profile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/mzansi_business_profile_view.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/profile_business_add.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/mzansi_set_up_business_profile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/personal_profile/mzansi_profile_view.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/components/mih_barcode_scanner.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/mih_wallet.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/pat_manager.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/add_or_view_patient.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/components/full_screen_file.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/patient_edit.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_profile/patient_profile.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_manager/pat_manager.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/components/full_screen_file.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/patient_profile.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_manager/pat_profile/patient_set_up.dart';
import 'package:provider/provider.dart';
import 'package:supertokens_flutter/supertokens.dart';
class MihGoRouterPaths {
@@ -50,7 +52,6 @@ class MihGoRouterPaths {
static const String businessProfileView = '/business-profile/view';
static const String patientProfile = '/patient-profile';
static const String patientProfileSetup = '/patient-profile/set-up';
static const String patientProfileEdit = '/patient-profile/edit';
static const String mzansiWallet = '/mzansi-wallet';
static const String mzansiDirectory = '/mzansi-directory';
static const String mihAccess = '/mih-access';
@@ -63,6 +64,7 @@ class MihGoRouterPaths {
static const String barcodeScanner = '/scanner';
static const String calculator = '/calculator';
static const String mzansiAi = '/mzansi-ai';
static const String mihMineSweeper = '/mih-minesweeper';
static const String packageDevTest = '/package-dev';
}
@@ -131,16 +133,8 @@ class MihGoRouter {
path: MihGoRouterPaths.mihHome,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: mihHome");
if (state.extra != null) {
final bool personalSelected = state.extra as bool;
return MihHome(
key: UniqueKey(),
personalSelected: personalSelected,
);
}
return MihHome(
key: UniqueKey(),
personalSelected: true,
);
},
),
@@ -150,14 +144,7 @@ class MihGoRouter {
path: MihGoRouterPaths.aboutMih,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: aboutMih");
final AboutArguments? args = state.extra as AboutArguments?;
int index = 0;
bool personalSelected = true;
if (args != null) {
index = args.packageIndex ?? 0;
personalSelected = args.personalSelected;
}
return AboutMih(arguments: AboutArguments(personalSelected, index));
return AboutMih();
},
),
// ========================== Mzansi Profile Personal ==================================
@@ -166,15 +153,13 @@ class MihGoRouter {
path: MihGoRouterPaths.mzansiProfileManage,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: mzansiProfileManage");
final AppProfileUpdateArguments? args =
state.extra as AppProfileUpdateArguments?;
if (args == null) {
if (context.watch<MzansiProfileProvider>().user == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
return const SizedBox.shrink();
}
return MzansiProfile(arguments: args);
return MzansiProfile();
},
),
GoRoute(
@@ -182,14 +167,15 @@ class MihGoRouter {
path: MihGoRouterPaths.mzansiProfileView,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: mzansiProfileView");
final AppUser? user = state.extra as AppUser?;
if (user == null) {
MzansiDirectoryProvider directoryProvider =
context.read<MzansiDirectoryProvider>();
if (directoryProvider.selectedUser == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
return const SizedBox.shrink();
}
return MzansiProfileView(user: user);
return MzansiProfileView();
},
),
// ========================== Mzansi Profile Business ==================================
@@ -198,8 +184,7 @@ class MihGoRouter {
path: MihGoRouterPaths.businessProfileManage,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: businessProfileManage");
final BusinessArguments? args = state.extra as BusinessArguments?;
if (args == null) {
if (context.watch<MzansiProfileProvider>().business == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
@@ -207,7 +192,6 @@ class MihGoRouter {
}
return MzansiBusinessProfile(
key: UniqueKey(),
arguments: args,
);
},
),
@@ -218,9 +202,10 @@ class MihGoRouter {
KenLogger.success("MihGoRouter: businessProfileView");
String? businessId = state.uri.queryParameters['business_id'];
KenLogger.success("businessId: $businessId");
final BusinessViewArguments? args =
state.extra as BusinessViewArguments?;
if (args == null && businessId == null) {
MzansiDirectoryProvider directoryProvider =
context.read<MzansiDirectoryProvider>();
if (directoryProvider.selectedBusiness == null &&
businessId == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
@@ -228,7 +213,6 @@ class MihGoRouter {
}
return MzansiBusinessProfileView(
key: UniqueKey(),
arguments: args,
businessId: businessId,
);
},
@@ -238,8 +222,7 @@ class MihGoRouter {
path: MihGoRouterPaths.businessProfileSetup,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: businessProfileSetup");
final AppUser? signedInUser = state.extra as AppUser?;
return ProfileBusinessAdd(signedInUser: signedInUser!);
return MzansiSetUpBusinessProfile();
},
),
// ========================== MIH Calculator ==================================
@@ -248,12 +231,7 @@ class MihGoRouter {
path: MihGoRouterPaths.calculator,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: mihCalculator");
final bool? personalSelected = state.extra as bool?;
bool personal = true;
if (personalSelected != null) {
personal = personalSelected;
}
return MIHCalculator(personalSelected: personal);
return MIHCalculator();
},
),
// ========================== MIH Calculator ==================================
@@ -262,8 +240,7 @@ class MihGoRouter {
path: MihGoRouterPaths.calendar,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: mihCalendar");
final CalendarArguments? args = state.extra as CalendarArguments?;
if (args == null) {
if (context.watch<MzansiProfileProvider>().user == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
@@ -271,7 +248,6 @@ class MihGoRouter {
}
return MzansiCalendar(
key: UniqueKey(),
arguments: args,
);
},
),
@@ -281,14 +257,13 @@ class MihGoRouter {
path: MihGoRouterPaths.mzansiAi,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: mzansiAi");
final MzansiAiArguments? args = state.extra as MzansiAiArguments?;
if (args == null) {
if (context.watch<MzansiProfileProvider>().user == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
return const SizedBox.shrink();
}
return MzansiAi(arguments: args);
return MzansiAi();
},
),
// ========================== Mzansi Wallet ==================================
@@ -297,8 +272,7 @@ class MihGoRouter {
path: MihGoRouterPaths.mzansiWallet,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: mzansiWallet");
final WalletArguments? args = state.extra as WalletArguments?;
if (args == null) {
if (context.watch<MzansiProfileProvider>().user == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
@@ -306,7 +280,6 @@ class MihGoRouter {
}
return MihWallet(
key: UniqueKey(),
arguments: args,
);
},
),
@@ -347,8 +320,8 @@ class MihGoRouter {
name: "mihAccess",
path: MihGoRouterPaths.mihAccess,
builder: (BuildContext context, GoRouterState state) {
final AppUser? signedInUser = state.extra as AppUser?;
if (signedInUser == null) {
KenLogger.success("MihGoRouter: mihAccess");
if (context.watch<MzansiProfileProvider>().user == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
@@ -356,7 +329,6 @@ class MihGoRouter {
}
return MihAccess(
key: UniqueKey(),
signedInUser: signedInUser,
);
},
),
@@ -365,44 +337,36 @@ class MihGoRouter {
name: "patientProfile",
path: MihGoRouterPaths.patientProfile,
builder: (BuildContext context, GoRouterState state) {
final PatientViewArguments? args =
state.extra as PatientViewArguments?;
if (args == null) {
KenLogger.success("MihGoRouter: patientProfile");
if (context.watch<MzansiProfileProvider>().user == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
return const SizedBox.shrink();
}
return AddOrViewPatient(
key: UniqueKey(),
arguments: args,
);
return PatientProfile();
},
),
GoRoute(
name: "patientProfileEdit",
path: MihGoRouterPaths.patientProfileEdit,
name: "patientProfileSetup",
path: MihGoRouterPaths.patientProfileSetup,
builder: (BuildContext context, GoRouterState state) {
final PatientEditArguments? args =
state.extra as PatientEditArguments?;
if (args == null) {
KenLogger.success("MihGoRouter: patientProfileSetup");
if (context.watch<MzansiProfileProvider>().user == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
return const SizedBox.shrink();
}
return EditPatient(
signedInUser: args.signedInUser,
selectedPatient: args.selectedPatient,
);
return PatientSetUp();
},
),
GoRoute(
name: "patientManager",
path: MihGoRouterPaths.patientManager,
builder: (BuildContext context, GoRouterState state) {
final PatManagerArguments? args = state.extra as PatManagerArguments?;
if (args == null) {
KenLogger.success("MihGoRouter: patientManager");
if (context.watch<MzansiProfileProvider>().business == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
@@ -410,7 +374,6 @@ class MihGoRouter {
}
return PatManager(
key: UniqueKey(),
arguments: args,
);
},
),
@@ -418,15 +381,14 @@ class MihGoRouter {
name: "patientManagerPatient",
path: MihGoRouterPaths.patientManagerPatient,
builder: (BuildContext context, GoRouterState state) {
final PatientViewArguments? args =
state.extra as PatientViewArguments?;
if (args == null) {
KenLogger.success("MihGoRouter: patientManagerPatient");
if (context.watch<MzansiProfileProvider>().user == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
return const SizedBox.shrink();
}
return PatientProfile(arguments: args);
return PatientProfile();
},
),
// ========================== Mzansi Directory ==================================
@@ -434,15 +396,14 @@ class MihGoRouter {
name: "mzansiDirectory",
path: MihGoRouterPaths.mzansiDirectory,
builder: (BuildContext context, GoRouterState state) {
final MzansiDirectoryArguments? args =
state.extra as MzansiDirectoryArguments?;
if (args == null) {
KenLogger.success("MihGoRouter: mzansiDirectory");
if (context.watch<MzansiProfileProvider>().user == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
return const SizedBox.shrink();
}
return MzansiDirectory(arguments: args);
return MzansiDirectory();
},
),
// ========================== End ==================================
@@ -450,6 +411,7 @@ class MihGoRouter {
name: "fileViewer",
path: MihGoRouterPaths.fileViewer,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: fileViewer");
final FileViewArguments? args = state.extra as FileViewArguments?;
return FullScreenFileViewer(arguments: args!);
},
@@ -458,11 +420,27 @@ class MihGoRouter {
name: "printPreview",
path: MihGoRouterPaths.printPreview,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: printPreview");
final PrintPreviewArguments? args =
state.extra as PrintPreviewArguments?;
return MIHPrintPreview(arguments: args!);
},
),
// ========================== MIH Minesweeper ==================================
GoRoute(
name: "mihMinesweeper",
path: MihGoRouterPaths.mihMineSweeper,
builder: (BuildContext context, GoRouterState state) {
KenLogger.success("MihGoRouter: mihMineSweeper");
if (context.watch<MzansiProfileProvider>().user == null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
context.go(MihGoRouterPaths.mihHome);
});
return const SizedBox.shrink();
}
return MihMineSweeper();
},
),
// ========================== End ==================================
// GoRoute(
// name: "notifications",

View File

@@ -1,19 +1,18 @@
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/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 {
final AboutArguments? arguments;
const AboutMih({
super.key,
this.arguments,
});
@override
@@ -21,21 +20,9 @@ class AboutMih extends StatefulWidget {
}
class _AboutMihState extends State<AboutMih> {
late int _selcetedIndex;
late bool _personalSelected;
@override
void initState() {
super.initState();
setState(() {
if (widget.arguments == null) {
_selcetedIndex = 0;
_personalSelected = true;
} else {
_selcetedIndex = widget.arguments!.packageIndex!;
_personalSelected = widget.arguments!.personalSelected;
}
});
}
@override
@@ -45,12 +32,9 @@ class _AboutMihState extends State<AboutMih> {
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
// print("Index: $_selcetedIndex");
selectedbodyIndex: context.watch<AboutMihProvider>().toolIndex,
onIndexChange: (newIndex) {
context.read<AboutMihProvider>().setToolIndex(newIndex);
},
);
}
@@ -62,7 +46,6 @@ class _AboutMihState extends State<AboutMih> {
onTap: () {
context.goNamed(
'mihHome',
extra: _personalSelected,
);
FocusScope.of(context).unfocus();
},
@@ -72,28 +55,20 @@ class _AboutMihState extends State<AboutMih> {
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.info)] = () {
setState(() {
_selcetedIndex = 0;
});
context.read<AboutMihProvider>().setToolIndex(0);
};
temp[const Icon(Icons.policy)] = () {
setState(() {
_selcetedIndex = 1;
});
context.read<AboutMihProvider>().setToolIndex(1);
};
temp[const Icon(Icons.design_services)] = () {
setState(() {
_selcetedIndex = 2;
});
context.read<AboutMihProvider>().setToolIndex(2);
};
temp[const Icon(Icons.star_rounded)] = () {
setState(() {
_selcetedIndex = 3;
});
context.read<AboutMihProvider>().setToolIndex(3);
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
selcetedIndex: context.watch<AboutMihProvider>().toolIndex,
);
}

View File

@@ -1,6 +1,5 @@
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
@@ -8,11 +7,9 @@ import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class AboutMihTile extends StatefulWidget {
final double packageSize;
final bool personalSelected;
const AboutMihTile({
super.key,
required this.packageSize,
required this.personalSelected,
});
@override
@@ -26,10 +23,6 @@ class _AboutMihTileState extends State<AboutMihTile> {
onTap: () {
context.goNamed(
"aboutMih",
extra: AboutArguments(
widget.personalSelected,
0,
),
);
// Navigator.of(context).pushNamed(
// '/about',

View File

@@ -506,8 +506,8 @@ class _MihInfoState extends State<MihInfo> {
void shareMIHLink(BuildContext context, String message, String link) {
String shareText = "$message: $link";
Share.share(
shareText,
SharePlus.instance.share(
ShareParams(text: shareText),
);
}
@@ -610,7 +610,7 @@ class _MihInfoState extends State<MihInfo> {
),
const SizedBox(width: 10),
Text(
"Users",
"People",
textAlign: TextAlign.center,
style: TextStyle(
fontWeight: FontWeight.normal,

View File

@@ -2,7 +2,10 @@ 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_components/mih_objects/patient_access.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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_components/mih_package_components/mih_button.dart';
@@ -10,18 +13,15 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_warning_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart';
import 'package:provider/provider.dart';
class BuildBusinessAccessList extends StatefulWidget {
final List<PatientAccess> patientAccessList;
final AppUser signedInUser;
final String filterText;
final void Function()? onSuccessUpate;
const BuildBusinessAccessList({
super.key,
required this.patientAccessList,
required this.signedInUser,
required this.filterText,
required this.onSuccessUpate,
});
@@ -60,18 +60,20 @@ class _BuildPatientsListState extends State<BuildBusinessAccessList> {
);
}
Widget displayQueue(int index) {
String line1 =
"Business Name: ${widget.patientAccessList[index].requested_by}";
Widget displayQueue(
MzansiProfileProvider mzansiProfileProvider,
MihAccessControllsProvider accessProvider,
int index,
List<PatientAccess> filteredList) {
String line1 = "Business Name: ${filteredList[index].requested_by}";
String line2 = "";
line2 +=
"Request Date: ${widget.patientAccessList[index].requested_on.substring(0, 16).replaceAll("T", " ")}\n";
line2 +=
"Profile Type: ${widget.patientAccessList[index].type.toUpperCase()}\n";
"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 = widget.patientAccessList[index].status.toUpperCase();
String access = filteredList[index].status.toUpperCase();
TextSpan accessWithColour;
if (access == "APPROVED") {
@@ -118,7 +120,7 @@ class _BuildPatientsListState extends State<BuildBusinessAccessList> {
// ),
// ),
onTap: () {
viewApprovalPopUp(index);
viewApprovalPopUp(mzansiProfileProvider, accessProvider, index);
},
// trailing: Icon(
// Icons.arrow_forward,
@@ -153,23 +155,24 @@ class _BuildPatientsListState extends State<BuildBusinessAccessList> {
}
}
void viewApprovalPopUp(int index) {
void viewApprovalPopUp(MzansiProfileProvider mzansiProfileProvider,
MihAccessControllsProvider accessProvider, int index) {
String subtitle =
"Business Name: ${widget.patientAccessList[index].requested_by}\n";
"Business Name: ${accessProvider.accessList![index].requested_by}\n";
subtitle +=
"Requested Date: ${widget.patientAccessList[index].requested_on.substring(0, 16).replaceAll("T", " ")}\n";
"Requested Date: ${accessProvider.accessList![index].requested_on.substring(0, 16).replaceAll("T", " ")}\n";
subtitle +=
"Profile Type: ${widget.patientAccessList[index].type.toUpperCase()}\n";
"Profile Type: ${accessProvider.accessList![index].type.toUpperCase()}\n";
subtitle +=
"Status: ${widget.patientAccessList[index].status.toUpperCase()}";
if (widget.patientAccessList[index].status == 'pending') {
"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: ${widget.patientAccessList[index].approved_by}\n";
"\nActioned By: ${accessProvider.accessList![index].approved_by}\n";
subtitle +=
"Actioned On: ${widget.patientAccessList[index].approved_on.substring(0, 16).replaceAll("T", " ")}";
"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.";
}
@@ -199,7 +202,7 @@ class _BuildPatientsListState extends State<BuildBusinessAccessList> {
),
const SizedBox(height: 20.0),
Visibility(
visible: widget.patientAccessList[index].status == 'pending',
visible: accessProvider.accessList![index].status == 'pending',
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
@@ -271,7 +274,7 @@ class _BuildPatientsListState extends State<BuildBusinessAccessList> {
),
),
Visibility(
visible: widget.patientAccessList[index].status == 'approved',
visible: accessProvider.accessList![index].status == 'approved',
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
@@ -338,7 +341,7 @@ class _BuildPatientsListState extends State<BuildBusinessAccessList> {
height: 20,
),
Visibility(
visible: widget.patientAccessList[index].status == 'pending',
visible: accessProvider.accessList![index].status == 'pending',
child: Wrap(
runSpacing: 10,
spacing: 10,
@@ -348,15 +351,20 @@ class _BuildPatientsListState extends State<BuildBusinessAccessList> {
print("request declined");
int statusCode = await MihAccessControlsServices()
.updatePatientAccessAPICall(
widget.patientAccessList[index].business_id,
widget.patientAccessList[index].requested_by,
widget.patientAccessList[index].app_id,
accessProvider.accessList![index].business_id,
accessProvider.accessList![index].requested_by,
accessProvider.accessList![index].app_id,
"declined",
"${widget.signedInUser.fname} ${widget.signedInUser.lname}",
widget.signedInUser,
"${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");
@@ -384,15 +392,20 @@ class _BuildPatientsListState extends State<BuildBusinessAccessList> {
print("request approved");
int statusCode = await MihAccessControlsServices()
.updatePatientAccessAPICall(
widget.patientAccessList[index].business_id,
widget.patientAccessList[index].requested_by,
widget.patientAccessList[index].app_id,
accessProvider.accessList![index].business_id,
accessProvider.accessList![index].requested_by,
accessProvider.accessList![index].app_id,
"approved",
"${widget.signedInUser.fname} ${widget.signedInUser.lname}",
widget.signedInUser,
"${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");
@@ -487,6 +500,16 @@ class _BuildPatientsListState extends State<BuildBusinessAccessList> {
);
}
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();
@@ -500,21 +523,30 @@ class _BuildPatientsListState extends State<BuildBusinessAccessList> {
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"),
return Consumer2<MzansiProfileProvider, MihAccessControllsProvider>(
builder: (BuildContext context,
MzansiProfileProvider mzansiProfileProvider,
MihAccessControllsProvider accessProvider,
Widget? child) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
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);
},
);
},
itemCount: widget.patientAccessList.length,
itemBuilder: (context, index) {
//final patient = widget.patients[index].id_no.contains(widget.searchString);
//print(index);
return displayQueue(index);
},
);
}
}

View File

@@ -2,15 +2,14 @@ import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart';
import 'package:mzansi_innovation_hub/mih_packages/access_review/package_tools/mih_access_requests.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class MihAccess extends StatefulWidget {
final AppUser signedInUser;
const MihAccess({
super.key,
required this.signedInUser,
});
@override
@@ -18,7 +17,6 @@ class MihAccess extends StatefulWidget {
}
class _MihAccessState extends State<MihAccess> {
int _selcetedIndex = 0;
@override
Widget build(BuildContext context) {
return MihPackage(
@@ -26,12 +24,9 @@ class _MihAccessState extends State<MihAccess> {
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selcetedIndex,
selectedbodyIndex: context.watch<MihAccessControllsProvider>().toolIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
print("Index: $_selcetedIndex");
context.read<MihAccessControllsProvider>().setToolIndex(newValue);
},
);
}
@@ -43,7 +38,6 @@ class _MihAccessState extends State<MihAccess> {
onTap: () {
context.goNamed(
'mihHome',
extra: true,
);
FocusScope.of(context).unfocus();
},
@@ -53,21 +47,17 @@ class _MihAccessState extends State<MihAccess> {
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.people)] = () {
setState(() {
_selcetedIndex = 0;
});
context.read<MihAccessControllsProvider>().setToolIndex(0);
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
selcetedIndex: context.watch<MihAccessControllsProvider>().toolIndex,
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
MihAccessRequest(
signedInUser: widget.signedInUser,
),
MihAccessRequest(),
];
return toolBodies;
}

View File

@@ -2,17 +2,14 @@ import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihAccessTile extends StatefulWidget {
final AppUser signedInUser;
final double packageSize;
const MihAccessTile({
super.key,
required this.signedInUser,
required this.packageSize,
});
@@ -28,7 +25,6 @@ class _MihAccessTileState extends State<MihAccessTile> {
onTap: () {
context.goNamed(
"mihAccess",
extra: widget.signedInUser,
);
// Navigator.of(context).pushNamed(
// '/mih-access',

View File

@@ -1,28 +1,24 @@
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_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_header.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/patient_access.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:flutter/material.dart';
import '../../../mih_services/mih_service_calls.dart';
import '../../../mih_components/mih_layout/mih_action.dart';
import '../../../mih_components/mih_layout/mih_header.dart';
import '../../../mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import '../../../mih_config/mih_env.dart';
import '../../../mih_components/mih_objects/app_user.dart';
import '../../../mih_components/mih_objects/patient_access.dart';
import '../builder/build_business_access_list.dart';
import 'package:provider/provider.dart';
class MihAccessRequest extends StatefulWidget {
final AppUser signedInUser;
const MihAccessRequest({
super.key,
required this.signedInUser,
});
@override
@@ -31,7 +27,7 @@ class MihAccessRequest extends StatefulWidget {
class _MihAccessRequestState extends State<MihAccessRequest> {
TextEditingController filterController = TextEditingController();
bool isLoading = true;
String baseUrl = AppEnviroment.baseApiUrl;
String errorCode = "";
@@ -41,35 +37,8 @@ class _MihAccessRequestState extends State<MihAccessRequest> {
bool forceRefresh = false;
late String selectedDropdown;
late Future<List<PatientAccess>> accessList;
// Future<List<AccessRequest>> fetchAccessRequests() async {
// //print("Patien manager page: $endpoint");
// final response = await http.get(
// Uri.parse("$baseUrl/access-requests/${widget.signedInUser.app_id}"));
// // print("Here");
// // print("Body: ${response.body}");
// // print("Code: ${response.statusCode}");
// errorCode = response.statusCode.toString();
// errorBody = response.body;
// if (response.statusCode == 200) {
// //print("Here1");
// Iterable l = jsonDecode(response.body);
// //print("Here2");
// List<AccessRequest> patientQueue = List<AccessRequest>.from(
// l.map((model) => AccessRequest.fromJson(model)));
// //print("Here3");
// //print(patientQueue);
// return patientQueue;
// } else {
// throw Exception('failed to load patients');
// }
// }
List<PatientAccess> filterSearchResults(List<PatientAccess> accessList) {
List<PatientAccess> templist = [];
for (var item in accessList) {
if (filterController.text == "All") {
templist.add(item);
@@ -83,16 +52,24 @@ class _MihAccessRequestState extends State<MihAccessRequest> {
}
void refreshList() {
MzansiProfileProvider mzansiProfileProvider =
context.read<MzansiProfileProvider>();
MihAccessControllsProvider accessProvider =
context.read<MihAccessControllsProvider>();
if (forceRefresh == true) {
MihAccessControlsServices().getBusinessAccessListOfPatient(
mzansiProfileProvider.user!.app_id,
accessProvider,
);
setState(() {
accessList = MIHApiCalls.getBusinessAccessListOfPatient(
widget.signedInUser.app_id);
forceRefresh = false;
});
} else if (selectedDropdown != filterController.text) {
MihAccessControlsServices().getBusinessAccessListOfPatient(
mzansiProfileProvider.user!.app_id,
accessProvider,
);
setState(() {
accessList = MIHApiCalls.getBusinessAccessListOfPatient(
widget.signedInUser.app_id);
selectedDropdown = filterController.text;
});
}
@@ -131,166 +108,92 @@ class _MihAccessRequestState extends State<MihAccessRequest> {
}
Widget getBody() {
return MihSingleChildScroll(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
return Consumer2<MzansiProfileProvider, MihAccessControllsProvider>(
builder: (BuildContext context,
MzansiProfileProvider mzansiProfileProvider,
MihAccessControllsProvider accessProvider,
Widget? child) {
if (isLoading) {
return const Center(
child: Mihloadingcircle(),
);
}
return MihSingleChildScroll(
child: Column(
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),
FutureBuilder(
future: accessList,
builder: (context, snapshot) {
//print("patient Queue List ${snapshot.hasData}");
if (snapshot.connectionState == ConnectionState.waiting) {
return const Mihloadingcircle();
} else if (snapshot.connectionState == ConnectionState.done) {
List<PatientAccess> accessRequestList;
accessRequestList = filterSearchResults(snapshot.requireData);
if (accessRequestList.isNotEmpty) {
return BuildBusinessAccessList(
signedInUser: widget.signedInUser,
patientAccessList: accessRequestList,
onSuccessUpate: () {
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();
},
);
} 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.accessControl,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
const SizedBox(height: 10),
Text(
"No access has been granted to your MIH Profile",
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."),
// ],
// ),
// ),
// ),
],
icon: const Icon(
Icons.refresh,
),
);
// return Center(
// child: Text(
// "No Request have been made.",
// style: TextStyle(
// fontSize: 25,
// color: MzansiInnovationHub.of(context)!
// .theme
// .messageTextColor()),
// textAlign: TextAlign.center,
// ),
// );
}
// return Expanded(
// child: displayAccessRequestList(accessRequestList),
// );
} else {
return Center(
child: Text(
"$errorCode: Error pulling Patients Data\n$baseUrl/queue/patients/\n$errorBody",
style: TextStyle(
fontSize: 25,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark")),
textAlign: TextAlign.center,
),
);
}
},
],
),
const SizedBox(height: 10),
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();
@@ -302,9 +205,8 @@ class _MihAccessRequestState extends State<MihAccessRequest> {
selectedDropdown = "All";
filterController.text = "All";
filterController.addListener(refreshList);
setState(() {
accessList = MIHApiCalls.getBusinessAccessListOfPatient(
widget.signedInUser.app_id);
WidgetsBinding.instance.addPostFrameCallback((_) async {
await initiasizeAccessList();
});
super.initState();
}

View File

@@ -2,16 +2,18 @@ import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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 {
final bool personalSelected;
const MIHCalculator({
super.key,
required this.personalSelected,
});
@override
@@ -19,7 +21,18 @@ class MIHCalculator extends StatefulWidget {
}
class _MIHCalculatorState extends State<MIHCalculator> {
int _selectedIndex = 0;
Future<void> getCurrencyCodeList() async {
await MihCurrencyExchangeRateServices.getCurrencyCodeList(context);
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
context.read<MihBannerAdProvider>().loadBannerAd();
await getCurrencyCodeList();
});
}
@override
Widget build(BuildContext context) {
@@ -28,12 +41,9 @@ class _MIHCalculatorState extends State<MIHCalculator> {
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selectedIndex,
onIndexChange: (newValue) {
setState(() {
_selectedIndex = newValue;
});
print("Index: $_selectedIndex");
selectedbodyIndex: context.watch<MihCalculatorProvider>().toolIndex,
onIndexChange: (newIndex) {
context.read<MihCalculatorProvider>().setToolIndex(newIndex);
},
);
}
@@ -45,7 +55,6 @@ class _MIHCalculatorState extends State<MIHCalculator> {
onTap: () {
context.goNamed(
'mihHome',
extra: widget.personalSelected,
);
FocusScope.of(context).unfocus();
},
@@ -55,23 +64,17 @@ class _MIHCalculatorState extends State<MIHCalculator> {
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.calculate)] = () {
setState(() {
_selectedIndex = 0;
});
context.read<MihCalculatorProvider>().setToolIndex(0);
};
temp[const Icon(Icons.money)] = () {
setState(() {
_selectedIndex = 1;
});
context.read<MihCalculatorProvider>().setToolIndex(1);
};
temp[const Icon(Icons.currency_exchange)] = () {
setState(() {
_selectedIndex = 2;
});
context.read<MihCalculatorProvider>().setToolIndex(2);
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selectedIndex,
selcetedIndex: context.watch<MihCalculatorProvider>().toolIndex,
);
}

View File

@@ -6,12 +6,10 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihCalculatorTile extends StatefulWidget {
final bool personalSelected;
final double packageSize;
const MihCalculatorTile({
super.key,
required this.personalSelected,
required this.packageSize,
});
@@ -26,12 +24,7 @@ class _MihCalculatorTileState extends State<MihCalculatorTile> {
onTap: () {
context.goNamed(
"mihCalculator",
extra: widget.personalSelected,
);
// Navigator.of(context).pushNamed(
// '/calculator',
// arguments: widget.personalSelected,
// );
},
appName: "Calculator",
appIcon: Icon(

View File

@@ -9,11 +9,13 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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});
@@ -28,8 +30,6 @@ class _CurrencyExchangeRateState extends State<CurrencyExchangeRate> {
final TextEditingController _toCurrencyController = TextEditingController();
final TextEditingController _fromAmountController = TextEditingController();
final TextEditingController _toAmountController = TextEditingController();
late Future<List<String>> availableCurrencies;
MihBannerAd _bannerAd = MihBannerAd();
Future<void> submitForm() async {
String fromCurrencyCode = _fromCurrencyController.text.split(" - ")[0];
@@ -67,9 +67,7 @@ class _CurrencyExchangeRateState extends State<CurrencyExchangeRate> {
fullscreen: false,
windowTitle: "Calculation Results",
onWindowTapClose: () {
setState(() {
_bannerAd = MihBannerAd();
});
context.read<MihBannerAdProvider>().loadBannerAd();
Navigator.pop(context);
},
windowBody: Column(
@@ -160,7 +158,9 @@ class _CurrencyExchangeRateState extends State<CurrencyExchangeRate> {
],
),
SizedBox(height: 10),
SizedBox(child: _bannerAd),
Consumer(builder: (context, bannerAdDisplay, child) {
return MihBannerAd();
}),
],
),
),
@@ -275,7 +275,6 @@ class _CurrencyExchangeRateState extends State<CurrencyExchangeRate> {
@override
void initState() {
super.initState();
availableCurrencies = MihCurrencyExchangeRateServices.getCurrencyCodeList();
}
@override
@@ -289,177 +288,155 @@ class _CurrencyExchangeRateState extends State<CurrencyExchangeRate> {
}
Widget getBody(double width) {
return FutureBuilder(
future: availableCurrencies,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Mihloadingcircle();
} else if (snapshot.connectionState == ConnectionState.done) {
return MihSingleChildScroll(
child: Padding(
padding: MzansiInnovationHub.of(context)!.theme.screenType ==
"desktop"
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(
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"),
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: snapshot.data!,
editable: true,
enableSearch: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
requiredText: true,
),
const SizedBox(height: 10),
MihDropdownField(
controller: _toCurrencyController,
hintText: "To",
dropdownOptions: snapshot.data!,
editable: true,
enableSearch: true,
validator: (value) {
return MihValidationServices().isEmpty(value);
},
requiredText: true,
),
const SizedBox(height: 15),
RichText(
textAlign: TextAlign.left,
text: TextSpan(
children: [
const TextSpan(
text: "* Experimental Feature: Please review "),
TextSpan(
text: "Diclaimer",
style: TextStyle(
fontSize: 15,
color: MihColors.getRedColor(
decoration: TextDecoration.underline,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontWeight: FontWeight.bold,
),
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."),
],
recognizer: TapGestureRecognizer()
..onTap = () {
displayDisclaimer();
},
),
),
const SizedBox(height: 25),
Center(
child: Wrap(
spacing: 10,
runSpacing: 10,
children: [
MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
submitForm();
FocusScope.of(context)
.requestFocus(FocusNode());
} else {
MihAlertServices()
.formNotFilledCompletely(context);
}
},
buttonColor: MihColors.getGreenColor(
const TextSpan(text: " before use."),
],
),
),
const SizedBox(height: 25),
Center(
child: Wrap(
spacing: 10,
runSpacing: 10,
children: [
MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
submitForm();
FocusScope.of(context)
.requestFocus(FocusNode());
} else {
MihAlertServices()
.formNotFilledCompletely(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"),
width: 300,
child: Text(
"Calculate",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
fontSize: 20,
fontWeight: FontWeight.bold,
),
MihButton(
onPressed: () {
clearInput();
},
buttonColor: MihColors.getRedColor(
),
),
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"),
width: 300,
child: Text(
"Clear",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
fontSize: 20,
fontWeight: FontWeight.bold,
),
],
),
),
),
],
],
),
),
],
),
),
);
} else {
return Center(
child: Text(
"Error pulling Currency Exchange Data.",
style: TextStyle(
fontSize: 25,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
textAlign: TextAlign.center,
),
);
}
});
],
),
),
);
},
);
}
}

View File

@@ -1,5 +1,6 @@
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_banner_ad.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_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_validation_services.dart';
@@ -14,6 +15,7 @@ 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_components/mih_package_components/mih_toggle.dart';
import 'package:provider/provider.dart';
class TipCalc extends StatefulWidget {
const TipCalc({super.key});
@@ -30,7 +32,6 @@ class _TipCalcState extends State<TipCalc> {
final ValueNotifier<String> splitValue = ValueNotifier("");
late bool splitPosition;
final _formKey = GlobalKey<FormState>();
MihBannerAd _bannerAd = MihBannerAd();
String tip = "";
String total = "";
String amountPerPerson = "";
@@ -98,9 +99,7 @@ class _TipCalcState extends State<TipCalc> {
fullscreen: false,
windowTitle: "Calculation Results",
onWindowTapClose: () {
setState(() {
_bannerAd = MihBannerAd();
});
context.read<MihBannerAdProvider>().loadBannerAd();
Navigator.pop(context);
},
windowBody: Column(
@@ -231,7 +230,9 @@ class _TipCalcState extends State<TipCalc> {
),
),
SizedBox(height: 10),
SizedBox(child: _bannerAd),
Consumer(builder: (context, bannerAdDisplay, child) {
return MihBannerAd();
}),
// if (splitBillController.text == "Yes") const Divider(),
],
),

View File

@@ -2,8 +2,11 @@ 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_components/mih_objects/appointment.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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';
@@ -17,18 +20,10 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/appointment.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class BuildAppointmentList extends StatefulWidget {
final List<Appointment> appointmentList;
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final bool personalSelected;
final bool inWaitingRoom;
final TextEditingController titleController;
final TextEditingController descriptionIDController;
@@ -38,11 +33,6 @@ class BuildAppointmentList extends StatefulWidget {
const BuildAppointmentList({
super.key,
required this.appointmentList,
required this.signedInUser,
required this.business,
required this.businessUser,
required this.personalSelected,
required this.inWaitingRoom,
required this.titleController,
required this.descriptionIDController,
@@ -77,22 +67,39 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
}
}
Widget displayAppointment(int index, double bodyWidth) {
String heading =
"${widget.appointmentList[index].date_time.split('T')[1].substring(0, 5)} - ${widget.appointmentList[index].title.toUpperCase()}";
String description = widget.appointmentList[index].description;
DateTime now = new DateTime.now();
int hourNow = int.parse(now.toString().split(' ')[1].substring(0, 2));
String date =
new DateTime(now.year, now.month, now.day).toString().split(' ')[0];
String appointDate = widget.appointmentList[index].date_time.split('T')[0];
int appointHour = int.parse(
widget.appointmentList[index].date_time.split('T')[1].substring(0, 2));
// print("Date Time Now: $now");
// print("Hour Now: $hourNow");
// print("Date: $date");
// print("Appointment Date: $appointDate");
// print("Appointment Hour: $appointHour");
Widget displayAppointment(MzansiProfileProvider mzansiProfileProvider,
MihCalendarProvider mihCalendarProvider, int index, double bodyWidth) {
List<Appointment> appointmentList = mzansiProfileProvider.personalHome
? mihCalendarProvider.personalAppointments!
: mihCalendarProvider.businessAppointments!;
String heading = "";
String description = "";
DateTime now;
int hourNow = 0;
String date = "";
int appointHour = 0;
String appointDate = "";
if (appointmentList[index].date_time.contains("T")) {
heading =
"${appointmentList[index].date_time.split('T')[1].substring(0, 5)} - ${appointmentList[index].title.toUpperCase()}";
description = appointmentList[index].description;
now = DateTime.now();
hourNow = int.parse(now.toString().split(' ')[1].substring(0, 2));
date = DateTime(now.year, now.month, now.day).toString().split(' ')[0];
appointDate = appointmentList[index].date_time.split('T')[0];
appointHour = int.parse(
appointmentList[index].date_time.split('T')[1].substring(0, 2));
} else {
heading =
"${appointmentList[index].date_time.split(' ')[1].substring(0, 5)} - ${appointmentList[index].title.toUpperCase()}";
description = appointmentList[index].description;
now = DateTime.now();
hourNow = int.parse(now.toString().split(' ')[1].substring(0, 2));
date = DateTime(now.year, now.month, now.day).toString().split(' ')[0];
appointDate = appointmentList[index].date_time.split(' ')[0];
appointHour = int.parse(
appointmentList[index].date_time.split(' ')[1].substring(0, 2));
}
Color appointmentColor = MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark");
if (date == appointDate) {
@@ -132,26 +139,28 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
),
onTap: () {
setState(() {
widget.titleController.text = widget.appointmentList[index].title;
widget.titleController.text = appointmentList[index].title;
widget.descriptionIDController.text =
widget.appointmentList[index].description;
appointmentList[index].description;
widget.dateController.text =
widget.appointmentList[index].date_time.split('T')[0];
widget.timeController.text = widget.appointmentList[index].date_time
.split('T')[1]
.substring(0, 5);
appointmentList[index].date_time.split('T')[0];
widget.timeController.text =
appointmentList[index].date_time.split('T')[1].substring(0, 5);
});
if (widget.inWaitingRoom == false) {
appointmentDetailsWindow(index, bodyWidth);
appointmentDetailsWindow(
mzansiProfileProvider, mihCalendarProvider, index, bodyWidth);
} else {
waitingRiinAppointmentDetailsWindow(index, bodyWidth);
waitingRoomAppointmentDetailsWindow(
mzansiProfileProvider, mihCalendarProvider, index, bodyWidth);
}
},
),
);
}
void appointmentDetailsWindow(int index, double bodyWidth) {
void appointmentDetailsWindow(MzansiProfileProvider mzansiProfileProvider,
MihCalendarProvider mihCalendarProvider, int index, double bodyWidth) {
showDialog(
context: context,
barrierDismissible: false,
@@ -177,7 +186,8 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
appointmentUpdateWindow(index, bodyWidth);
appointmentUpdateWindow(mzansiProfileProvider,
mihCalendarProvider, index, bodyWidth);
},
),
SpeedDialChild(
@@ -197,7 +207,8 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
deleteAppointmentConfirmationWindow(index);
deleteAppointmentConfirmationWindow(
mzansiProfileProvider, mihCalendarProvider, index);
},
),
],
@@ -273,7 +284,11 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
);
}
void waitingRiinAppointmentDetailsWindow(int index, double bodyWidth) {
void waitingRoomAppointmentDetailsWindow(
MzansiProfileProvider mzansiProfileProvider,
MihCalendarProvider mihCalendarProvider,
int index,
double bodyWidth) {
showDialog(
context: context,
barrierDismissible: false,
@@ -299,7 +314,8 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
appointmentUpdateWindow(index, bodyWidth);
appointmentUpdateWindow(mzansiProfileProvider,
mihCalendarProvider, index, bodyWidth);
},
),
SpeedDialChild(
@@ -319,7 +335,8 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
backgroundColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onTap: () {
deleteAppointmentConfirmationWindow(index);
deleteAppointmentConfirmationWindow(
mzansiProfileProvider, mihCalendarProvider, index);
},
),
],
@@ -405,7 +422,11 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
);
}
void appointmentUpdateWindow(int index, double bodyWidth) {
void appointmentUpdateWindow(MzansiProfileProvider mzansiProfileProvider,
MihCalendarProvider mihCalendarProvider, int index, double bodyWidth) {
List<Appointment> appointmentList = mzansiProfileProvider.personalHome
? mihCalendarProvider.personalAppointments!
: mihCalendarProvider.businessAppointments!;
showDialog(
context: context,
barrierDismissible: false,
@@ -415,13 +436,13 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
windowTitle: "Update Appointment",
onWindowTapClose: () {
setState(() {
widget.titleController.text = widget.appointmentList[index].title;
widget.titleController.text = appointmentList[index].title;
widget.descriptionIDController.text =
widget.appointmentList[index].description;
appointmentList[index].description;
widget.dateController.text =
widget.appointmentList[index].date_time.split('T')[0];
widget.timeController.text = widget
.appointmentList[index].date_time
appointmentList[index].date_time.split('T')[0];
widget.timeController.text = appointmentList[index]
.date_time
.split('T')[1]
.substring(0, 5);
});
@@ -497,7 +518,8 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
updateAppointmentCall(index);
updateAppointmentCall(mzansiProfileProvider,
mihCalendarProvider, index);
} else {
MihAlertServices()
.formNotFilledCompletely(context);
@@ -542,7 +564,10 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
}
}
void deleteAppointmentConfirmationWindow(int index) {
void deleteAppointmentConfirmationWindow(
MzansiProfileProvider mzansiProfileProvider,
MihCalendarProvider mihCalendarProvider,
int index) {
showDialog(
context: context,
barrierDismissible: false,
@@ -550,46 +575,55 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
return MIHDeleteMessage(
deleteType: "Appointment",
onTap: () {
deleteAppointmentCall(index);
deleteAppointmentCall(
mzansiProfileProvider, mihCalendarProvider, index);
});
},
);
}
Future<void> updateAppointmentCall(int index) async {
Future<void> updateAppointmentCall(
MzansiProfileProvider mzansiProfileProvider,
MihCalendarProvider mihCalendarProvider,
int index) async {
int statusCode;
if (isAppointmentInputValid()) {
if (widget.personalSelected == true) {
List<Appointment> appointmentList = mzansiProfileProvider.personalHome
? mihCalendarProvider.personalAppointments!
: mihCalendarProvider.businessAppointments!;
if (mzansiProfileProvider.personalHome == true) {
statusCode = await MihMzansiCalendarApis.updatePersonalAppointment(
widget.signedInUser,
widget.business,
mzansiProfileProvider.user!,
mzansiProfileProvider.business,
null,
widget.appointmentList[index].idappointments,
appointmentList[index].idappointments,
widget.titleController.text,
widget.descriptionIDController.text,
widget.dateController.text,
widget.timeController.text,
mihCalendarProvider,
context,
);
} else if (widget.personalSelected == false &&
} else if (mzansiProfileProvider.personalHome == false &&
widget.inWaitingRoom == false) {
statusCode = await MihMzansiCalendarApis.updateBusinessAppointment(
widget.signedInUser,
widget.business,
widget.businessUser,
widget.appointmentList[index].idappointments,
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(
widget.signedInUser,
widget.business,
widget.businessUser,
widget.appointmentList[index].idappointments,
mzansiProfileProvider.user!,
mzansiProfileProvider.business,
mzansiProfileProvider.businessUser,
appointmentList[index].idappointments,
widget.titleController.text,
widget.descriptionIDController.text,
widget.dateController.text,
@@ -604,27 +638,20 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
KenLogger.warning("calendar route");
context.goNamed(
"mihCalendar",
extra: CalendarArguments(
widget.signedInUser,
widget.personalSelected,
widget.business,
widget.businessUser,
),
);
} else {
KenLogger.warning("waiting room route");
// GoRouter.of(context).refresh();
context.goNamed(
'mihHome',
extra: false,
);
context.goNamed(
'patientManager',
extra: PatManagerArguments(
widget.signedInUser,
mzansiProfileProvider.user!,
false,
widget.business,
widget.businessUser,
mzansiProfileProvider.business,
mzansiProfileProvider.businessUser,
),
);
// context.pop();
@@ -642,22 +669,26 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
}
}
Future<void> deleteAppointmentCall(int index) async {
Future<void> deleteAppointmentCall(
MzansiProfileProvider mzansiProfileProvider,
MihCalendarProvider mihCalendarProvider,
int index) async {
List<Appointment> appointmentList = mzansiProfileProvider.personalHome
? mihCalendarProvider.personalAppointments!
: mihCalendarProvider.businessAppointments!;
int statucCode = await MihMzansiCalendarApis.deleteAppointmentAPICall(
widget.signedInUser,
widget.personalSelected,
widget.business,
widget.businessUser,
mzansiProfileProvider.user!,
mzansiProfileProvider.personalHome,
mzansiProfileProvider.business,
mzansiProfileProvider.businessUser,
widget.inWaitingRoom,
widget.appointmentList[index].idappointments,
appointmentList[index].idappointments,
mihCalendarProvider,
context,
);
if (statucCode == 200) {
context.pop();
context.pop();
setState(() {
widget.appointmentList.removeAt(index);
});
successPopUp("Successfully Deleted Appointment",
"You appointment has been successfully deleted from your calendar.");
} else {
@@ -730,20 +761,24 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
);
}
bool canEditAppointment(int index) {
if (widget.personalSelected == true &&
widget.appointmentList[index].app_id == widget.signedInUser.app_id &&
widget.appointmentList[index].business_id == "") {
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 (widget.personalSelected == false &&
widget.appointmentList[index].business_id ==
widget.business!.business_id &&
widget.appointmentList[index].app_id.isEmpty) {
} else if (mzansiProfileProvider.personalHome == false &&
appointmentList[index].business_id ==
mzansiProfileProvider.business!.business_id &&
appointmentList[index].app_id.isEmpty) {
return true;
} else if (widget.personalSelected == false &&
widget.appointmentList[index].business_id ==
widget.business!.business_id &&
widget.appointmentList[index].app_id.isNotEmpty) {
} else if (mzansiProfileProvider.personalHome == false &&
appointmentList[index].business_id ==
mzansiProfileProvider.business!.business_id &&
appointmentList[index].app_id.isNotEmpty) {
return true;
} else {
return false;
@@ -765,16 +800,27 @@ class _BuildAppointmentListState extends State<BuildAppointmentList> {
width = size.width;
height = size.height;
});
return Padding(
padding: EdgeInsets.symmetric(horizontal: getPaddingSize()),
child: ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: widget.appointmentList.length,
itemBuilder: (context, index) {
return displayAppointment(index, width);
},
),
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(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: appointmentList.length,
itemBuilder: (context, index) {
return displayAppointment(
mzansiProfileProvider, mihCalendarProvider, index, width);
},
),
);
},
);
}
}

View File

@@ -2,15 +2,15 @@ import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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:provider/provider.dart';
class MzansiCalendar extends StatefulWidget {
final CalendarArguments arguments;
const MzansiCalendar({
super.key,
required this.arguments,
});
@override
@@ -18,8 +18,6 @@ class MzansiCalendar extends StatefulWidget {
}
class _MzansiCalendarState extends State<MzansiCalendar> {
int _selcetedIndex = 0;
@override
Widget build(BuildContext context) {
return MihPackage(
@@ -27,12 +25,9 @@ class _MzansiCalendarState extends State<MzansiCalendar> {
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
print("Index: $_selcetedIndex");
selectedbodyIndex: context.watch<MihCalendarProvider>().toolIndex,
onIndexChange: (newIndex) {
context.read<MihCalendarProvider>().setToolIndex(newIndex);
},
);
}
@@ -42,10 +37,9 @@ class _MzansiCalendarState extends State<MzansiCalendar> {
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
// Navigator.of(context).pop();
context.read<MihCalendarProvider>().resetSelectedDay();
context.goNamed(
'mihHome',
extra: widget.arguments.personalSelected,
);
FocusScope.of(context).unfocus();
},
@@ -55,33 +49,28 @@ class _MzansiCalendarState extends State<MzansiCalendar> {
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.calendar_month)] = () {
setState(() {
_selcetedIndex = 0;
});
context.read<MihCalendarProvider>().setToolIndex(0);
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
selcetedIndex: context.watch<MihCalendarProvider>().toolIndex,
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
//appointment here
Appointments(
signedInUser: widget.arguments.signedInUser,
business: widget.arguments.business,
businessUser: widget.arguments.businessUser,
personalSelected: widget.arguments.personalSelected,
),
Appointments(),
];
return toolBodies;
}
List<String> getToolTitle() {
MzansiProfileProvider mzansiProfileProvider =
context.read<MzansiProfileProvider>();
List<String> toolTitles = [
widget.arguments.personalSelected == true ? "Personal" : "Business",
mzansiProfileProvider.personalHome == true ? "Personal" : "Business",
];
return toolTitles;
}

View File

@@ -2,17 +2,14 @@ import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MzansiCalendarTile extends StatefulWidget {
final CalendarArguments arguments;
final double packageSize;
const MzansiCalendarTile({
super.key,
required this.arguments,
required this.packageSize,
});
@@ -27,7 +24,6 @@ class _MzansiCalendarTileState extends State<MzansiCalendarTile> {
onTap: () {
context.goNamed(
"mihCalendar",
extra: widget.arguments,
);
// Navigator.of(context).pushNamed(
// '/calendar',

View File

@@ -1,7 +1,13 @@
import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_calendar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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';
@@ -17,29 +23,12 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_time_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/appointment.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_packages/calendar/builder/build_appointment_list.dart';
import 'package:flutter/material.dart';
import '../../../main.dart';
import '../../../mih_components/mih_package_components/mih_calendar.dart';
import '../../../mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import '../../../mih_config/mih_env.dart';
import '../../../mih_components/mih_objects/app_user.dart';
import 'package:provider/provider.dart';
class Appointments extends StatefulWidget {
final AppUser signedInUser;
final Business? business;
final BusinessUser? businessUser;
final bool personalSelected;
const Appointments({
super.key,
required this.signedInUser,
required this.business,
required this.businessUser,
required this.personalSelected,
});
@override
@@ -57,25 +46,18 @@ class _PatientAccessRequestState extends State<Appointments> {
TextEditingController();
final TextEditingController _appointmentTimeController =
TextEditingController();
String baseUrl = AppEnviroment.baseApiUrl;
String selectedDay = DateTime.now().toString().split(" ")[0];
late Future<List<Appointment>> personalAppointmentResults;
late Future<List<Appointment>> businessAppointmentResults;
late Future<List<Appointment>> appointmentResults;
bool isLoading = true;
final _formKey = GlobalKey<FormState>();
Widget displayAppointmentList(List<Appointment> appointmentList) {
Widget displayAppointmentList(MzansiProfileProvider mzansiProfileProvider,
MihCalendarProvider mihCalendarProvider) {
List<Appointment> appointmentList = mzansiProfileProvider.personalHome
? mihCalendarProvider.personalAppointments!
: mihCalendarProvider.businessAppointments!;
if (appointmentList.isNotEmpty) {
return Expanded(
child: BuildAppointmentList(
appointmentList: appointmentList,
signedInUser: widget.signedInUser,
business: widget.business,
businessUser: widget.businessUser,
personalSelected: widget.personalSelected,
inWaitingRoom: false,
titleController: _appointmentTitleController,
descriptionIDController: _appointmentDescriptionIDController,
@@ -101,7 +83,7 @@ class _PatientAccessRequestState extends State<Appointments> {
),
const SizedBox(height: 10),
Text(
"No appointments for $selectedDay",
"No appointments for ${mihCalendarProvider.selectedDay}",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: TextStyle(
@@ -147,7 +129,8 @@ class _PatientAccessRequestState extends State<Appointments> {
);
}
void addAppointmentWindow(double width) {
void addAppointmentWindow(MzansiProfileProvider mzansiProfileProvider,
MihCalendarProvider mihCalendarProvider, double width) {
showDialog(
context: context,
barrierDismissible: false,
@@ -227,7 +210,8 @@ class _PatientAccessRequestState extends State<Appointments> {
child: MihButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
addAppointmentCall();
addAppointmentCall(
mzansiProfileProvider, mihCalendarProvider);
} else {
MihAlertServices().formNotFilledCompletely(context);
}
@@ -269,28 +253,33 @@ class _PatientAccessRequestState extends State<Appointments> {
}
}
Future<void> addAppointmentCall() async {
Future<void> addAppointmentCall(
MzansiProfileProvider mzansiProfileProvider,
MihCalendarProvider mihCalendarProvider,
) async {
if (isAppointmentInputValid()) {
int statusCode;
if (widget.personalSelected == false) {
if (mzansiProfileProvider.personalHome == false) {
statusCode = await MihMzansiCalendarApis.addBusinessAppointment(
widget.signedInUser,
widget.business!,
widget.businessUser!,
mzansiProfileProvider.user!,
mzansiProfileProvider.business!,
mzansiProfileProvider.businessUser!,
false,
_appointmentTitleController.text,
_appointmentDescriptionIDController.text,
_appointmentDateController.text,
_appointmentTimeController.text,
mihCalendarProvider,
context,
);
} else {
statusCode = await MihMzansiCalendarApis.addPersonalAppointment(
widget.signedInUser,
mzansiProfileProvider.user!,
_appointmentTitleController.text,
_appointmentDescriptionIDController.text,
_appointmentDateController.text,
_appointmentTimeController.text,
mihCalendarProvider,
context,
);
}
@@ -298,20 +287,20 @@ class _PatientAccessRequestState extends State<Appointments> {
context.pop();
successPopUp("Successfully Added Appointment",
"You appointment has been successfully added to your calendar.");
setState(() {
if (widget.personalSelected) {
appointmentResults = MihMzansiCalendarApis.getPersonalAppointments(
widget.signedInUser.app_id,
selectedDay,
);
} else {
appointmentResults = MihMzansiCalendarApis.getBusinessAppointments(
widget.business!.business_id,
false,
selectedDay,
);
}
});
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 {
internetConnectionPopUp();
}
@@ -397,8 +386,8 @@ class _PatientAccessRequestState extends State<Appointments> {
);
}
String getTitle() {
if (widget.personalSelected == false) {
String getTitle(MzansiProfileProvider mzansiProfileProvider) {
if (mzansiProfileProvider.personalHome == false) {
return "Business Appointments";
} else {
return "Personal Appointments";
@@ -407,108 +396,114 @@ class _PatientAccessRequestState extends State<Appointments> {
void checkforchange() {
setState(() {
if (widget.personalSelected == false) {
appointmentResults = MihMzansiCalendarApis.getBusinessAppointments(
widget.business!.business_id,
false,
selectedDay,
);
} else {
appointmentResults = MihMzansiCalendarApis.getPersonalAppointments(
widget.signedInUser.app_id,
selectedDay,
);
}
isLoading = true;
});
_loadInitialAppointments();
}
Widget getBody(double width) {
return Stack(
children: [
MihSingleChildScroll(
child: Column(
children: [
MIHCalendar(
calendarWidth: 500,
rowHeight: 35,
setDate: (value) {
setState(() {
selectedDay = value;
selectedAppointmentDateController.text = selectedDay;
});
}),
// Divider(
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
Row(
mainAxisSize: MainAxisSize.max,
if (isLoading) {
return const Center(
child: Mihloadingcircle(),
);
}
return Consumer2<MzansiProfileProvider, MihCalendarProvider>(
builder: (BuildContext context,
MzansiProfileProvider mzansiProfileProvider,
MihCalendarProvider mihCalendarProvider,
Widget? child) {
return Stack(
children: [
MihSingleChildScroll(
child: Column(
children: [
FutureBuilder(
future: appointmentResults,
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return const Expanded(
child: Center(child: Mihloadingcircle()));
} else if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
return displayAppointmentList(snapshot.requireData);
} else {
return Center(
child: Text(
"Error pulling appointments",
style: TextStyle(
fontSize: 25,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark")),
textAlign: TextAlign.center,
),
);
}
MIHCalendar(
calendarWidth: 500,
rowHeight: 35,
setDate: (value) {
mihCalendarProvider.setSelectedDay(value);
setState(() {
selectedAppointmentDateController.text = value;
});
}),
// Divider(
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
Row(
mainAxisSize: MainAxisSize.max,
children: [
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(width);
},
)
],
),
),
],
),
),
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();
@@ -522,19 +517,8 @@ class _PatientAccessRequestState extends State<Appointments> {
@override
void initState() {
selectedAppointmentDateController.addListener(checkforchange);
setState(() {
if (widget.personalSelected == false) {
appointmentResults = MihMzansiCalendarApis.getBusinessAppointments(
widget.business!.business_id,
false,
selectedDay,
);
} else {
appointmentResults = MihMzansiCalendarApis.getPersonalAppointments(
widget.signedInUser.app_id,
selectedDay,
);
}
WidgetsBinding.instance.addPostFrameCallback((_) async {
_loadInitialAppointments();
});
super.initState();
}

View File

@@ -4,8 +4,10 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/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});
@@ -15,56 +17,35 @@ class MihAuthentication extends StatefulWidget {
}
class _MihAuthenticationState extends State<MihAuthentication> {
int _selcetedIndex = 0;
@override
Widget build(BuildContext context) {
return MihPackage(
appActionButton: getAction(),
appTools: getTools(),
appBody: getToolBody(),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
selectedbodyIndex: context.watch<MihAuthenticationProvider>().toolIndex,
onIndexChange: (newIndex) {
context.read<MihAuthenticationProvider>().setToolIndex(newIndex);
},
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
MihSignIn(
onNewUserButtonTap: () {
setState(() {
_selcetedIndex = 1;
});
},
),
MihRegister(onExistingUserButtonTap: () {
setState(() {
_selcetedIndex = 0;
});
})
];
List<Widget> toolBodies = [MihSignIn(), MihRegister()];
return toolBodies;
}
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.perm_identity)] = () {
setState(() {
_selcetedIndex = 0;
});
context.read<MihAuthenticationProvider>().setToolIndex(0);
};
temp[const Icon(Icons.create)] = () {
setState(() {
_selcetedIndex = 1;
});
context.read<MihAuthenticationProvider>().setToolIndex(1);
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
selcetedIndex: context.watch<MihAuthenticationProvider>().toolIndex,
);
}
@@ -75,7 +56,7 @@ class _MihAuthenticationState extends State<MihAuthentication> {
icon: const Icon(MihIcons.mihLogo),
iconSize: 45,
onTap: () {
context.goNamed("aboutMih", extra: 0);
context.goNamed("aboutMih", extra: true);
},
),
);

View File

@@ -11,19 +11,20 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_authentication_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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 {
final void Function()? onExistingUserButtonTap;
const MihRegister({
super.key,
required this.onExistingUserButtonTap,
});
@override
@@ -75,6 +76,7 @@ class _MihRegisterState extends State<MihRegister> {
}
Future<void> signUserUp() async {
context.read<MzansiProfileProvider>().reset();
if (!validEmail()) {
emailError();
} else if (passwordController.text != confirmPasswordController.text) {
@@ -366,7 +368,11 @@ class _MihRegisterState extends State<MihRegister> {
),
),
MihButton(
onPressed: widget.onExistingUserButtonTap,
onPressed: () {
context
.read<MihAuthenticationProvider>()
.setToolIndex(0);
},
buttonColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),

View File

@@ -9,18 +9,19 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_authentication_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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 {
final void Function()? onNewUserButtonTap;
const MihSignIn({
super.key,
required this.onNewUserButtonTap,
});
@override
@@ -39,6 +40,7 @@ class _MihSignInState extends State<MihSignIn> {
//sign user in
Future<void> signUserIn() async {
context.read<MzansiProfileProvider>().reset();
try {
successfulSignIn = await MihAuthenticationServices().signUserIn(
emailController.text,
@@ -381,7 +383,11 @@ class _MihSignInState extends State<MihSignIn> {
),
),
MihButton(
onPressed: widget.onNewUserButtonTap,
onPressed: () {
context
.read<MihAuthenticationProvider>()
.setToolIndex(1);
},
buttonColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),

View File

@@ -1,21 +1,27 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/about_mih_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_access_controlls_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_authentication_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calculator_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_calendar_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_wallet_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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 {
final AppUser signedInUser;
final ImageProvider<Object>? propicFile;
const MIHAppDrawer({
super.key,
required this.signedInUser,
required this.propicFile,
});
@override
@@ -25,6 +31,21 @@ class MIHAppDrawer extends StatefulWidget {
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
@@ -32,19 +53,30 @@ class _MIHAppDrawerState extends State<MIHAppDrawer> {
return true;
}
Widget displayProPic() {
Widget displayProPic(MzansiProfileProvider mzansiProfileProvider) {
return GestureDetector(
onTap: () {
context.goNamed(
'mzansiProfileManage',
extra: AppProfileUpdateArguments(
widget.signedInUser,
widget.propicFile,
),
);
if (mzansiProfileProvider.personalHome) {
context.goNamed(
'mzansiProfileManage',
);
} else {
if (mzansiProfileProvider.business == null) {
context.goNamed(
'businessProfileSetup',
extra: mzansiProfileProvider.user,
);
} else {
context.goNamed(
"businessProfileManage",
);
}
}
},
child: MihCircleAvatar(
imageFile: widget.propicFile,
imageFile: mzansiProfileProvider.personalHome
? mzansiProfileProvider.userProfilePicture
: mzansiProfileProvider.businessProfilePicture,
width: 60,
editable: false,
fileNameController: proPicController,
@@ -66,9 +98,6 @@ class _MIHAppDrawerState extends State<MIHAppDrawer> {
@override
void initState() {
setState(() {
profilePictureLoaded = displayProPic();
});
super.initState();
}
@@ -76,287 +105,329 @@ class _MIHAppDrawerState extends State<MIHAppDrawer> {
Widget build(BuildContext context) {
// precacheImage(
// MzansiInnovationHub.of(context)!.theme.logoImage().image, context);
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,
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: [
DrawerHeader(
decoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
child: SizedBox(
height: 400,
width: constraints.maxWidth,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
profilePictureLoaded,
Text(
"${widget.signedInUser.fname} ${widget.signedInUser.lname}",
style: TextStyle(
fontWeight: FontWeight.bold,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
),
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"),
),
),
],
),
Text(
"@${widget.signedInUser.username}",
style: TextStyle(
fontSize: 12,
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,
);
},
),
),
Text(
widget.signedInUser.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.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"),
),
),
),
// 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: () {
context.goNamed(
"aboutMih",
extra: AboutArguments(
true,
1,
),
);
},
),
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: () {
context.goNamed(
"aboutMih",
extra: AboutArguments(
true,
2,
),
);
},
),
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) {
context.goNamed(
'mihHome',
extra: true,
);
// Navigator.of(context).pop();
// Navigator.of(context).popAndPushNamed(
// '/',
// arguments: AuthArguments(true, false),
// );
}
},
),
],
),
// 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,
// ),
// ),
),
],
),
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).pop();
Navigator.of(context).popAndPushNamed(
'/',
arguments: AuthArguments(true, false),
);
// Navigator.of(context).popAndPushNamed('/',);
});
},
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,
// ),
// ),
),
],
);
},
),
),
);
},
),
),
);
},
);
}
}

View File

@@ -1,7 +1,8 @@
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_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/user_consent.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
@@ -13,22 +14,24 @@ import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_scack_bar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/about_mih_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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_packages/mih_home/components/mih_app_drawer.dart';
import 'package:mzansi_innovation_hub/mih_packages/mih_home/mih_home_error.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_service_calls.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_my_business_user_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_user_consent_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable
class MihHome extends StatefulWidget {
final bool personalSelected;
const MihHome({
super.key,
required this.personalSelected,
});
@override
@@ -36,14 +39,77 @@ class MihHome extends StatefulWidget {
}
class _MihHomeState extends State<MihHome> {
final proPicController = TextEditingController();
late int _selcetedIndex;
late bool _personalSelected;
late Future<HomeArguments> profileData;
late Future<UserConsent?> futureUserConsent;
bool showUserConsent = false;
DateTime latestPrivacyPolicyDate = DateTime.parse("2024-12-01");
DateTime latestTermOfServiceDate = DateTime.parse("2024-12-01");
bool _isLoadingInitialData = true;
Future<void> _loadInitialData() async {
if (mounted) {
setState(() {
_isLoadingInitialData = true;
});
}
MzansiProfileProvider mzansiProfileProvider =
context.read<MzansiProfileProvider>();
// Note: getUserData sets user and userProfilePicUrl in the provider
if (mzansiProfileProvider.user == null) {
await getUserData();
}
// Note: getUserConsentStatus sets userConsent in the provider
if (mzansiProfileProvider.userConsent == null) {
await getUserConsentStatus();
}
// 1. Get Business Data
if (mzansiProfileProvider.user != null &&
mzansiProfileProvider.user!.type == "business" &&
mzansiProfileProvider.business == null) {
KenLogger.success(mzansiProfileProvider.business == null
? "Business is null, fetching business data..."
: "Business data already loaded.");
await getBusinessData();
}
// 2. Set state after all data is loaded
if (mounted) {
setState(() {
_isLoadingInitialData = false;
});
}
}
Future<void> getBusinessData() async {
AppUser? user = context.read<MzansiProfileProvider>().user;
String logoUrl;
String signatureUrl;
Business? responseBusiness =
await MihBusinessDetailsServices().getBusinessDetailsByUser(context);
// if (responseBusiness == null && user!.type == "business") {
// if (mounted) {
// context.goNamed(
// 'businessProfileSetup',
// extra: user,
// );
// }
// }
if (responseBusiness != null && user!.type == "business") {
// Get Business
// Business Profile Set Up aleary
logoUrl = await MihFileApi.getMinioFileUrl(
context.read<MzansiProfileProvider>().business!.logo_path,
context,
);
context.read<MzansiProfileProvider>().setBusinessProfilePicUrl(logoUrl);
// Get Business User
await MihMyBusinessUserServices().getBusinessUser(context);
signatureUrl = await MihFileApi.getMinioFileUrl(
context.read<MzansiProfileProvider>().businessUser!.sig_path,
context,
);
context
.read<MzansiProfileProvider>()
.setBusinessUserSignatureUrl(signatureUrl);
}
}
bool showPolicyWindow(UserConsent? userConsent) {
if (userConsent == null) {
@@ -60,20 +126,19 @@ class _MihHomeState extends State<MihHome> {
}
}
void createOrUpdateAccpetance(UserConsent? userConsent, String app_id) {
void createOrUpdateAccpetance(MzansiProfileProvider mzansiProfileProvider) {
UserConsent? userConsent = mzansiProfileProvider.userConsent;
userConsent != null
? MihUserConsentServices()
.updateUserConsentStatus(
app_id,
DateTime.now().toIso8601String(),
DateTime.now().toIso8601String(),
mzansiProfileProvider,
context,
)
.then((value) {
if (value == 200) {
// setState(() {
// showUserConsent = false;
// });
context.goNamed("mihHome", extra: false);
context.goNamed("mihHome");
ScaffoldMessenger.of(context).showSnackBar(
MihSnackBar(
child: Text("Thank you for accepting our Policies"),
@@ -89,16 +154,14 @@ class _MihHomeState extends State<MihHome> {
})
: MihUserConsentServices()
.insertUserConsentStatus(
app_id,
DateTime.now().toIso8601String(),
DateTime.now().toIso8601String(),
mzansiProfileProvider,
context,
)
.then((value) {
if (value == 201) {
// setState(() {
// showUserConsent = false;
// });
context.goNamed("mihHome", extra: false);
context.goNamed("mihHome");
ScaffoldMessenger.of(context).showSnackBar(
MihSnackBar(
child: Text("Thank you for accepting our Policies"),
@@ -114,6 +177,25 @@ class _MihHomeState extends State<MihHome> {
});
}
Future<void> getUserData() async {
if (!mounted) return;
String url;
await MihUserServices().getUserDetails(
context,
);
if (!mounted) return;
url = await MihFileApi.getMinioFileUrl(
context.read<MzansiProfileProvider>().user!.pro_pic_path,
context,
);
context.read<MzansiProfileProvider>().setUserProfilePicUrl(url);
}
Future<void> getUserConsentStatus() async {
if (!mounted) return;
await MihUserConsentServices().getUserConsentStatus(context);
}
@override
void dispose() {
super.dispose();
@@ -122,19 +204,7 @@ class _MihHomeState extends State<MihHome> {
@override
void initState() {
super.initState();
profileData = MIHApiCalls().getProfile(10, context);
futureUserConsent = MihUserConsentServices().getUserConsentStatus();
if (widget.personalSelected == true) {
setState(() {
_selcetedIndex = 0;
_personalSelected = true;
});
} else {
setState(() {
_selcetedIndex = 1;
_personalSelected = false;
});
}
_loadInitialData();
}
List<String> getToolTitle() {
@@ -147,375 +217,339 @@ class _MihHomeState extends State<MihHome> {
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: profileData,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
return Consumer<MzansiProfileProvider>(
builder: (BuildContext context,
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
if (_isLoadingInitialData) {
return Scaffold(
body: const Mihloadingcircle(
// message: "Fetching your Data...",
),
body: Center(
child: Mihloadingcircle(),
),
);
} else if (asyncSnapshot.connectionState == ConnectionState.done &&
asyncSnapshot.hasData) {
return Stack(
children: [
MihPackage(
appActionButton: getAction(asyncSnapshot.data!.profilePicUrl),
appTools: getTools(
asyncSnapshot.data!.signedInUser.type != "personal"),
appBody: getToolBody(asyncSnapshot.data!),
appToolTitles: getToolTitle(),
actionDrawer: getActionDrawer(
asyncSnapshot.data!.signedInUser,
asyncSnapshot.data!.profilePicUrl,
}
// 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);
},
),
),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
if (_selcetedIndex == 0) {
setState(() {
_selcetedIndex = newValue;
_personalSelected = true;
});
} else {
setState(() {
_selcetedIndex = newValue;
_personalSelected = false;
});
}
},
),
FutureBuilder(
future: futureUserConsent,
builder: (context, asyncSnapshotUserConsent) {
if (asyncSnapshotUserConsent.connectionState ==
ConnectionState.waiting) {
showUserConsent = false;
} else if (asyncSnapshotUserConsent.connectionState ==
ConnectionState.done &&
asyncSnapshotUserConsent.hasData) {
showUserConsent =
showPolicyWindow(asyncSnapshotUserConsent.data);
} else if (asyncSnapshotUserConsent.connectionState ==
ConnectionState.done &&
!asyncSnapshotUserConsent.hasData) {
showUserConsent = true;
} else {
showUserConsent = false;
}
return Visibility(
visible: showUserConsent,
child: Container(
color: Colors.black.withValues(alpha: 0.5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
MihPackageWindow(
fullscreen: false,
windowTitle:
"Privacy Policy & Terms Of Service Alert!",
onWindowTapClose: () {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.warning_amber_rounded,
size: 100,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark",
),
),
alertTitle:
"Oops, Looks like you missed a step!",
alertBody: Text(
"We're excited for you to keep using the MIH app! Before you do, please take a moment to accept our Privacy Policy and Terms of Service. Thanks for helping us keep your experience great!",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark",
),
fontSize: 15,
fontWeight: FontWeight.normal,
),
),
alertColour: MihColors.getRedColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark",
),
);
});
},
windowBody: Column(
children: [
Icon(
Icons.policy,
size: 150,
),
Visibility(
visible: showPolicyWindow(mzansiProfileProvider.userConsent),
child: Container(
color: Colors.black.withValues(alpha: 0.5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
MihPackageWindow(
fullscreen: false,
windowTitle: "Privacy Policy & Terms Of Service Alert!",
onWindowTapClose: () {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.warning_amber_rounded,
size: 100,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark",
),
),
alertTitle:
"Oops, Looks like you missed a step!",
alertBody: Text(
"We're excited for you to keep using the MIH app! Before you do, please take a moment to accept our Privacy Policy and Terms of Service. Thanks for helping us keep your experience great!",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark",
),
fontSize: 15,
fontWeight: FontWeight.normal,
),
const SizedBox(height: 10),
Text(
"Welcome to the MIH App",
textAlign: TextAlign.center,
),
alertColour: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark",
),
);
});
},
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: 15,
fontWeight: FontWeight.normal,
),
),
const SizedBox(height: 20),
Center(
child: Wrap(
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.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark",
),
fontSize: 30,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
fontSize: 20,
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,
),
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.getSecondaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark",
),
fontSize: 15,
fontWeight: FontWeight.normal,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!
.theme
.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 20),
Center(
child: Wrap(
alignment: WrapAlignment.center,
spacing: 10,
runSpacing: 10,
children: [
MihButton(
onPressed: () {
context.goNamed(
"aboutMih",
extra: AboutArguments(
widget.personalSelected,
1,
),
);
},
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: () {
context.goNamed(
"aboutMih",
extra: AboutArguments(
widget.personalSelected,
2,
),
);
},
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(
asyncSnapshotUserConsent.data,
asyncSnapshot
.data!.signedInUser.app_id,
);
},
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,
),
),
),
],
),
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),
],
),
),
],
),
],
),
),
const SizedBox(height: 10),
],
),
);
}),
],
);
} else {
return MihHomeError(
errorMessage: asyncSnapshot.hasError
? asyncSnapshot.error.toString()
: "An unknown error occurred",
);
}
),
],
),
),
),
],
);
},
);
}
Widget getAction(String proPicUrl) {
Widget getAction() {
return Builder(builder: (context) {
return MihPackageAction(
icon: Padding(
padding: const EdgeInsets.only(left: 5.0),
child: MihCircleAvatar(
imageFile: proPicUrl != "" ? NetworkImage(proPicUrl) : null,
width: 50,
editable: false,
fileNameController: proPicController,
userSelectedfile: null,
// frameColor: frameColor,
frameColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
backgroundColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
onChange: (_) {},
),
// MIHProfilePicture(
// profilePictureFile: widget.propicFile,
// proPicController: proPicController,
// proPic: null,
// width: 45,
// radius: 21,
// drawerMode: false,
// editable: false,
// frameColor: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// onChange: (newProPic) {},
// ),
),
iconSize: 45,
onTap: () {
Scaffold.of(context).openDrawer();
FocusScope.of(context)
.requestFocus(FocusNode()); // Fully unfocus all fields
// FocusScope.of(context).unfocus(); // Unfocus any text fields
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(AppUser signedInUser, String proPicUrl) {
return MIHAppDrawer(
signedInUser: signedInUser,
propicFile: proPicUrl != "" ? NetworkImage(proPicUrl) : null,
);
MIHAppDrawer getActionDrawer() {
return MIHAppDrawer();
}
MihPackageTools getTools(bool isBusinessUser) {
MihPackageTools getTools(
MzansiProfileProvider mzansiProfileProvider, bool isBusinessUser) {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.person)] = () {
setState(() {
_selcetedIndex = 0;
_personalSelected = true;
mzansiProfileProvider.setPersonalHome(true);
});
};
if (isBusinessUser) {
temp[const Icon(Icons.business_center)] = () {
setState(() {
_selcetedIndex = 1;
_personalSelected = false;
mzansiProfileProvider.setPersonalHome(false);
});
};
}
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
selcetedIndex: mzansiProfileProvider.personalHome ? 0 : 1,
);
}
List<Widget> getToolBody(HomeArguments profData) {
List<Widget> getToolBody(MzansiProfileProvider mzansiProfileProvider) {
List<Widget> toolBodies = [];
AppUser? user = mzansiProfileProvider.user;
Business? business = mzansiProfileProvider.business;
BusinessUser? businessUser = mzansiProfileProvider.businessUser;
String userProfilePictureUrl =
mzansiProfileProvider.userProfilePicUrl ?? "";
toolBodies.add(
MihPersonalHome(
signedInUser: profData.signedInUser,
personalSelected: _personalSelected,
business: profData.business,
businessUser: profData.businessUser,
propicFile: profData.profilePicUrl != ""
? NetworkImage(profData.profilePicUrl)
signedInUser: user!,
personalSelected: mzansiProfileProvider.personalHome,
business: business,
businessUser: businessUser,
propicFile: userProfilePictureUrl != ""
? NetworkImage(userProfilePictureUrl)
: null,
isDevActive: AppEnviroment.getEnv() == "Dev",
isUserNew: profData.signedInUser.username == "",
isUserNew: user.username == "",
),
);
if (profData.signedInUser.type != "personal") {
if (user.type != "personal") {
toolBodies.add(
MihBusinessHome(
signedInUser: profData.signedInUser,
personalSelected: _personalSelected,
businessUser: profData.businessUser,
business: profData.business,
isBusinessUserNew: profData.businessUser == null,
isLoading: _isLoadingInitialData,
),
);
}

View File

@@ -4,10 +4,9 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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';
@@ -16,22 +15,15 @@ import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tiles/mzans
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/package_tiles/mzansi_directory_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_business_profile_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tiles/mzansi_setup_business_profile_tile.dart';
import 'package:mzansi_innovation_hub/mih_packages/patient_profile/pat_manager/package_tiles/pat_manager_tile.dart';
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 AppUser signedInUser;
final bool personalSelected;
final Business? business;
final BusinessUser? businessUser;
final bool isBusinessUserNew;
final bool isLoading;
const MihBusinessHome({
super.key,
required this.signedInUser,
required this.personalSelected,
required this.business,
required this.businessUser,
required this.isBusinessUserNew,
required this.isLoading,
});
@override
@@ -70,7 +62,6 @@ class _MihBusinessHomeState extends State<MihBusinessHome>
List<Map<String, Widget>> temp = [];
temp.add({
"Setup Business": MzansiSetupBusinessProfileTile(
signedInUser: widget.signedInUser,
packageSize: packageSize,
)
});
@@ -78,15 +69,25 @@ class _MihBusinessHomeState extends State<MihBusinessHome>
}
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(
arguments: BusinessArguments(
widget.signedInUser,
widget.businessUser,
widget.business,
),
packageSize: packageSize,
)
});
@@ -94,10 +95,10 @@ class _MihBusinessHomeState extends State<MihBusinessHome>
temp.add({
"Patient Manager": PatManagerTile(
arguments: PatManagerArguments(
widget.signedInUser,
mzansiProfileProvider.user!,
false,
widget.business,
widget.businessUser,
mzansiProfileProvider.business!,
mzansiProfileProvider.businessUser!,
),
packageSize: packageSize,
)
@@ -105,12 +106,6 @@ class _MihBusinessHomeState extends State<MihBusinessHome>
//=============== Calendar ===============
temp.add({
"Calendar": MzansiCalendarTile(
arguments: CalendarArguments(
widget.signedInUser,
false,
widget.business,
widget.businessUser,
),
packageSize: packageSize,
)
});
@@ -118,24 +113,17 @@ class _MihBusinessHomeState extends State<MihBusinessHome>
temp.add({
"Mzansi Directory": MzansiDirectoryTile(
packageSize: packageSize,
personalSelected: false,
)
});
//=============== Calculator ===============
temp.add({
"Calculator": MihCalculatorTile(
personalSelected: widget.personalSelected,
packageSize: packageSize,
)
});
//=============== Mzansi AI ===============
temp.add({
"Mzansi AI": MzansiAiTile(
arguments: MzansiAiArguments(
widget.signedInUser,
"",
false,
),
packageSize: packageSize,
)
});
@@ -143,7 +131,6 @@ class _MihBusinessHomeState extends State<MihBusinessHome>
temp.add({
"About MIH": AboutMihTile(
packageSize: packageSize,
personalSelected: false,
)
});
return temp;
@@ -194,19 +181,9 @@ class _MihBusinessHomeState extends State<MihBusinessHome>
void initState() {
super.initState();
searchController.addListener(searchPackage);
if (widget.isBusinessUserNew) {
businessPackagesMap = setNewBusinessUserPackages();
} else {
businessPackagesMap = setBusinessPackages();
}
businessPackagesMap = setBusinessPackages();
searchPackage();
//Scrolling Banner message
// _marqueeController = AnimationController(
// vsync: this,
// duration: const Duration(seconds: 12),
// );
// _scrollController = ScrollController();
// WidgetsBinding.instance.addPostFrameCallback((_) => _startMarquee());
}
@override
@@ -221,123 +198,106 @@ class _MihBusinessHomeState extends State<MihBusinessHome>
}
Widget getBody(double width, double height) {
return MihSingleChildScroll(
child: Column(
children: [
// Icon(
// MihIcons.mihLogo,
// size: width / 2,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// const SizedBox(height: 10),
// Text(
// // "Welcome, ${widget.signedInUser.fname}!",
// "Mzansi Innovation Hub",
// textAlign: TextAlign.center,
// style: TextStyle(
// fontSize: 30,
// fontWeight: FontWeight.bold,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
// const SizedBox(height: 20),
Visibility(
visible: !widget.isBusinessUserNew,
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: () {
context.goNamed(
"mzansiAi",
extra: MzansiAiArguments(
widget.signedInUser,
searchController.text.isEmpty
? null
: searchController.text,
false,
),
);
// Navigator.of(context).pushNamed(
// '/mzansi-ai',
// arguments: MzansiAiArguments(
// widget.signedInUser,
// searchController.text.isEmpty
// ? null
// : searchController.text,
// ),
// );
searchController.clear();
},
searchFocusNode: _searchFocusNode,
),
),
),
const SizedBox(height: 20),
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(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: getPadding(width, height),
// shrinkWrap: true,
itemCount: filteredPackages.length,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: packageSize,
crossAxisSpacing: 5,
return Consumer2<MzansiProfileProvider, MzansiAiProvider>(
builder: (BuildContext context,
MzansiProfileProvider mzansiProfileProvider,
MzansiAiProvider mzansiAiProvider,
Widget? child) {
// if (mzansiProfileProvider.user == null ||
// mzansiProfileProvider.business == null ||
// mzansiProfileProvider.businessUser == null) {
// return Center(
// child: Mihloadingcircle(),
// );
// }
return MihSingleChildScroll(
child: 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
.setStartUpQuestion(searchController.text);
context.goNamed(
"mzansiAi",
);
searchController.clear();
},
searchFocusNode: _searchFocusNode,
),
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"),
),
),
const SizedBox(height: 20),
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(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: getPadding(width, height),
// shrinkWrap: true,
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"),
),
),
],
);
}
},
),
],
),
],
),
);
},
);
}
}

View File

@@ -9,18 +9,21 @@ import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_user.dart';
import 'package:mzansi_innovation_hub/mih_components/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_profile/pat_profile/package_tiles/patient_profile_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:provider/provider.dart';
class MihPersonalHome extends StatefulWidget {
final AppUser signedInUser;
@@ -78,8 +81,6 @@ class _MihPersonalHomeState extends State<MihPersonalHome>
List<Map<String, Widget>> temp = [];
temp.add({
"Setup Profile": MzansiSetupProfileTile(
signedInUser: widget.signedInUser,
propicFile: widget.propicFile,
packageSize: packageSize,
)
});
@@ -91,15 +92,12 @@ class _MihPersonalHomeState extends State<MihPersonalHome>
//=============== Mzansi Profile ===============
temp.add({
"Mzansi Profile": MzansiProfileTile(
signedInUser: widget.signedInUser,
propicFile: widget.propicFile,
packageSize: packageSize,
)
});
//=============== Mzansi Wallet ===============
temp.add({
"Mzansi Wallet": MihWalletTile(
signedInUser: widget.signedInUser,
packageSize: packageSize,
)
});
@@ -120,35 +118,29 @@ class _MihPersonalHomeState extends State<MihPersonalHome>
temp.add({
"Mzansi Directory": MzansiDirectoryTile(
packageSize: packageSize,
personalSelected: true,
)
});
//=============== Calendar ===============
temp.add({
"Calendar": MzansiCalendarTile(
arguments: CalendarArguments(
widget.signedInUser,
true,
widget.business,
widget.businessUser,
),
packageSize: packageSize,
)
});
//=============== Mzansi AI ===============
temp.add({
"Mzansi AI": MzansiAiTile(
arguments: MzansiAiArguments(
widget.signedInUser,
"",
true,
),
packageSize: packageSize,
)
});
//=============== Calculator ===============
temp.add({
"Calculator": MihCalculatorTile(
packageSize: packageSize,
)
});
//=============== Mine Sweeper ===============
temp.add({
"Mine Sweeper": MihMineSweeperTile(
personalSelected: widget.personalSelected,
packageSize: packageSize,
)
@@ -156,7 +148,6 @@ class _MihPersonalHomeState extends State<MihPersonalHome>
//=============== MIH Access ===============
temp.add({
"MIH Access": MihAccessTile(
signedInUser: widget.signedInUser,
packageSize: packageSize,
)
});
@@ -164,7 +155,6 @@ class _MihPersonalHomeState extends State<MihPersonalHome>
temp.add({
"About MIH": AboutMihTile(
packageSize: packageSize,
personalSelected: true,
)
});
//=============== Dev ===============
@@ -259,124 +249,115 @@ class _MihPersonalHomeState extends State<MihPersonalHome>
}
Widget getBody(double width, double height) {
return MihSingleChildScroll(
child: Column(
children: [
// Icon(
// MihIcons.mihLogo,
// size: 200,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// const SizedBox(height: 10),
// Text(
// // "Welcome, ${widget.signedInUser.fname}!",
// "Mzansi Innovation Hub",
// textAlign: TextAlign.center,
// style: TextStyle(
// fontSize: 30,
// fontWeight: FontWeight.bold,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
// const SizedBox(height: 20),
Visibility(
visible: !widget.isUserNew,
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: () {
context.goNamed(
"mzansiAi",
extra: MzansiAiArguments(
widget.signedInUser,
searchController.text.isEmpty
? null
: searchController.text,
true,
),
);
// Navigator.of(context).pushNamed(
// '/mzansi-ai',
// arguments: MzansiAiArguments(
// widget.signedInUser,
// searchController.text.isEmpty
// ? null
// : searchController.text,
// ),
// );
searchController.clear();
},
searchFocusNode: _searchFocusNode,
),
),
),
const SizedBox(height: 20),
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(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: getPadding(width, height),
// shrinkWrap: true,
itemCount: filteredPackages.length,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: packageSize,
crossAxisSpacing: 5,
return Consumer<MzansiAiProvider>(
builder: (BuildContext context, MzansiAiProvider mzansiAiProvider,
Widget? child) {
return MihSingleChildScroll(
child: Column(
children: [
// Icon(
// MihIcons.mihLogo,
// size: 200,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// const SizedBox(height: 10),
// Text(
// // "Welcome, ${widget.signedInUser.fname}!",
// "Mzansi Innovation Hub",
// textAlign: TextAlign.center,
// style: TextStyle(
// fontSize: 30,
// fontWeight: FontWeight.bold,
// color: MihColors.getSecondaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
// const SizedBox(height: 20),
Visibility(
visible: !widget.isUserNew,
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
.setStartUpQuestion(searchController.text);
context.goNamed(
"mzansiAi",
);
searchController.clear();
},
searchFocusNode: _searchFocusNode,
),
itemBuilder: (context, index) {
return filteredPackages[index];
// return personalPackages[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"),
),
),
const SizedBox(height: 20),
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(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: getPadding(width, height),
// shrinkWrap: true,
itemCount: filteredPackages.length,
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: packageSize,
crossAxisSpacing: 5,
),
),
],
);
}
},
itemBuilder: (context, index) {
return filteredPackages[index];
// return personalPackages[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"),
),
),
],
);
}
},
),
],
),
],
),
);
},
);
}
}

View File

@@ -0,0 +1,113 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
itemCount: mineSweeperProvider.leaderboard!.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),
MihCircleAvatar(
key: UniqueKey(),
imageFile:
mineSweeperProvider.leaderboardUserPictures.isNotEmpty
? mineSweeperProvider.leaderboardUserPictures[index]
: null,
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),
),
),
],
)
],
),
);
},
);
},
);
}
}

View File

@@ -0,0 +1,96 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
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),
),
),
],
)
],
),
);
},
);
},
);
}
}

View File

@@ -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,
});
}

View File

@@ -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_components/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),
);
},
);
}
}

View File

@@ -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_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/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,
),
),
),
),
],
),
],
);
},
),
);
}
}

View 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_components/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),
),
);
}
}

View File

@@ -0,0 +1,101 @@
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_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_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:provider/provider.dart';
class MihMineSweeper extends StatefulWidget {
const MihMineSweeper({super.key});
@override
State<MihMineSweeper> createState() => _MihMineSweeperState();
}
class _MihMineSweeperState extends State<MihMineSweeper> {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) async {
context.read<MihBannerAdProvider>().loadBannerAd();
});
}
@override
Widget build(BuildContext context) {
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() {
List<Widget> toolBodies = [
const MineSweeperGame(),
const MihMineSweeperLeaderBoard(),
const MyScoreBoard(),
const MineSweeperQuickStartGuide(),
];
return toolBodies;
}
}

View File

@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MihMineSweeperTile extends StatefulWidget {
final bool personalSelected;
final double packageSize;
const MihMineSweeperTile({
super.key,
required this.personalSelected,
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,
primaryColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
secondaryColor: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
}
}

View File

@@ -0,0 +1,198 @@
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_components/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/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();
Future<void> initialiseLeaderboard() async {
MihMineSweeperProvider mineSweeperProvider =
context.read<MihMineSweeperProvider>();
filterController.text = mineSweeperProvider.difficulty;
KenLogger.success("getting data");
await MihMinesweeperServices().getTop20Leaderboard(mineSweeperProvider);
List<ImageProvider<Object>?> userPictures = [];
String userPicUrl = "";
for (final ranking in mineSweeperProvider.leaderboard!) {
userPicUrl = await MihFileApi.getMinioFileUrl(ranking.proPicUrl, context);
userPictures.add(NetworkImage(userPicUrl));
}
mineSweeperProvider.setLeaderboardUserPictures(
leaderboardUserPictures: userPictures);
}
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 Consumer<MihMineSweeperProvider>(
builder: (BuildContext context,
MihMineSweeperProvider mineSweeperProvider, Widget? child) {
if (mineSweeperProvider.leaderboard == null) {
return Center(
child: Mihloadingcircle(),
);
} else {
return SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: 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),
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"),
],
),
),
),
],
),
)
: BuildMinesweeperLeaderboardList(),
],
),
);
}
},
);
}
}

View File

@@ -0,0 +1,813 @@
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_components/mih_package_components/mih_banner_ad.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_banner_ad_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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,
MihBannerAdProvider addProvider) {
// easy - 10 * 10 & 15 bombs
// Intermediate - 10 * 15 & 23 bombs
// Hard - 10 * 20 & 30 bombs
addProvider.loadBannerAd();
showDialog(
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,
MihBannerAdProvider adProvider,
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
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
FontAwesomeIcons.bomb,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 100,
),
),
alertTitle: "Better Luck Next Time",
alertBody: Column(
children: [
Text(
"Your lost this game of MIH Minesweeper!!!",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
const SizedBox(height: 10),
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,
spacing: 10,
runSpacing: 10,
children: [
MihButton(
onPressed: () {
context.pop();
showStartGameWindow(
mihMineSweeperProvider, adProvider);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"New Game",
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.getOrangeColor(
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,
),
),
),
],
),
],
),
alertColour: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
);
});
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, adProvider);
// 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,
MihBannerAdProvider adProvider,
) async {
// Game is won if all non-mine squares are opened.
if (squaresLeft <= mihMineSweeperProvider.totalMines) {
stopTimer();
isGameWon = true;
isGameOver = true;
// win alert
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.celebration,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
size: 100,
),
alertTitle: "Congratulations",
alertBody: Column(
children: [
Text(
"Your won this game of MIH Minesweeper!!!",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
const SizedBox(height: 10),
// Text(
// "You took ${_formatTime()} to complete the game on ${mihMineSweeperProvider.difficulty} mode.",
// style: TextStyle(
// fontSize: 15,
// color: MihColors.getSecondaryColor(
// MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
// const SizedBox(height: 10),
Text(
"Time Taken: ${_formatTime().replaceAll("00:", "")}",
style: TextStyle(
fontSize: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
const SizedBox(height: 10),
Text(
"Score: ${calculateGameScore(mihMineSweeperProvider)}",
style: TextStyle(
fontSize: 20,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
const SizedBox(height: 20),
Wrap(
runAlignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
spacing: 10,
runSpacing: 10,
children: [
MihButton(
onPressed: () {
context.pop();
showStartGameWindow(mihMineSweeperProvider, adProvider);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
width: 300,
child: Text(
"New Game",
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.getOrangeColor(
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,
),
),
),
],
),
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
);
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;
}
}
@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 Consumer3<MzansiProfileProvider, MihMineSweeperProvider,
MihBannerAdProvider>(
builder: (BuildContext context,
MzansiProfileProvider profileProvider,
MihMineSweeperProvider mihMineSweeperProvider,
MihBannerAdProvider adProvider,
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,
adProvider,
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(2);
},
),
SpeedDialChild(
child: Icon(
Icons.add,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
label: board.isEmpty && squaresLeft < 0
? "Start Game"
: "Reset 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, adProvider);
},
),
]),
)
],
),
),
MihBannerAd(),
SizedBox(height: 15),
],
);
},
);
}
}

View File

@@ -0,0 +1,350 @@
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_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> {
Widget _buildSectionTitle(String title) {
return Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
);
}
Widget _buildSubSectionTitle(String title) {
return Text(
title,
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w600,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
);
}
Widget _buildRulePoint({
required String title,
required List<String> points,
required Color color,
}) {
return Padding(
padding:
const EdgeInsets.only(left: 8.0, right: 8.0, top: 4.0, bottom: 4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: color,
),
),
...points
.map((point) => Padding(
padding: const EdgeInsets.only(left: 10.0),
child: Text(
'$point',
style: TextStyle(
fontSize: 16,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
))
.toList(),
],
),
);
}
Widget _buildNumberClue(String clue, String explanation) {
return Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 4.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text('',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
Expanded(
child: RichText(
text: TextSpan(
style: TextStyle(
fontSize: 16,
color: MihColors.getOrangeColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
children: <TextSpan>[
TextSpan(
text: 'If you see a $clue: ',
style: const TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: explanation),
],
),
),
),
],
),
);
}
Widget _buildStrategyPoint(String title, String explanation,
{bool isAction = false}) {
return Padding(
padding: const EdgeInsets.only(right: 8.0, left: 8.0, bottom: 4.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
style: TextStyle(
fontSize: 16,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
children: <TextSpan>[
TextSpan(
text: title,
style: TextStyle(
fontWeight: isAction ? FontWeight.bold : FontWeight.normal,
color: isAction
? MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode !=
"Dark")
: MihColors.getPurpleColor(
MzansiInnovationHub.of(context)!.theme.mode !=
"Dark"),
),
),
TextSpan(text: isAction ? ' $explanation' : ': $explanation'),
],
),
),
],
),
);
}
Widget _buildTipPoint(String title, String explanation) {
return Padding(
padding: const EdgeInsets.only(left: 8.0, bottom: 4.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('',
style: TextStyle(
fontSize: 18,
color: MihColors.getBronze(
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
fontWeight: FontWeight.bold)),
Expanded(
child: RichText(
text: TextSpan(
style: TextStyle(
fontSize: 16,
color: MihColors.getBronze(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
children: <TextSpan>[
TextSpan(
text: title,
style: const TextStyle(fontWeight: FontWeight.bold)),
TextSpan(text: explanation),
],
),
),
),
],
),
);
}
@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: 16),
),
// const Divider(height: 30),
const SizedBox(height: 15),
// --- 1. Two Main Actions ---
Container(
decoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
borderRadius: BorderRadius.circular(15),
),
child: Column(
children: [
const SizedBox(height: 8),
_buildSectionTitle('1. Two Main Actions (Your Controls)'),
const SizedBox(height: 8),
_buildRulePoint(
title: 'Quick Tap (or Click): This is the Dig action.',
points: [
'Goal: To uncover a square and see a number clue.',
'Risk: If you click a mine, the game ends!',
],
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
),
_buildRulePoint(
title:
'Tap and Hold (or Long Press): This is the Flag action (🚩).',
points: [
'Goal: To safely mark a square that you are **certain** is a mine.',
'Benefit: You cannot accidentally click a square that is flagged.',
],
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode != "Dark"),
),
const SizedBox(height: 4),
],
),
),
const SizedBox(height: 15),
// --- 2. The Golden Rule: Reading the Numbers ---
Container(
decoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
borderRadius: BorderRadius.circular(15),
),
child: Column(
children: [
const SizedBox(height: 8),
_buildSectionTitle('2. The Golden Rule: Reading the Numbers'),
const SizedBox(height: 8),
Text(
'The number tells you exactly how many mines are touching that square (including sides and corners).',
style: TextStyle(
fontSize: 18,
fontStyle: FontStyle.italic,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode !=
"Darl"),
),
),
const SizedBox(height: 8),
_buildNumberClue('Blank Space (a \'0\')',
'Zero (0) mines are touching it. All surrounding squares are safe, and the game will open them for you automatically.'),
_buildNumberClue('\'1\'',
'Only **one** mine is touching this square. You must find and flag that single mine.'),
_buildNumberClue('\'3\'',
'Three mines are touching this square. You must find and flag all three.'),
const SizedBox(height: 4),
],
),
),
const SizedBox(height: 15),
// --- 3. The Winning Strategy ---
Container(
decoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
borderRadius: BorderRadius.circular(15),
),
child: Column(
children: [
const SizedBox(height: 8),
_buildSectionTitle(
'3. The Winning Strategy (The Deduction Loop)'),
const SizedBox(height: 8),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: 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(
fontSize: 18,
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode !=
"Darl"),
),
),
),
const SizedBox(height: 8),
_buildSubSectionTitle('A. Find the Mines (Where to Flag 🚩)'),
_buildStrategyPoint(
'Look for a number that only has one choice for a mine.',
'Example: If a \'1\' is touching only one hidden square, that hidden square **must** be the mine.'),
_buildStrategyPoint('Action:',
'Tap and Hold to place a **Flag** on the square you are sure is a mine.',
isAction: true),
const SizedBox(height: 12),
_buildSubSectionTitle(
'B. Find the Safe Squares (Where to Dig)'),
_buildStrategyPoint(
'Look for a number that has been \'satisfied\' by your flags.',
'Example: You see a \'2\'. You have already placed two 🚩 flags touching it. The \'2\' is satisfied.'),
_buildStrategyPoint('Action:',
'Quick Tap any of the remaining hidden squares touching that \'satisfied\' number. They **must be safe** because the mine requirement has already been met.',
isAction: true),
],
),
),
const SizedBox(height: 15),
// --- Key Beginner Tip ---
Container(
decoration: BoxDecoration(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode != "Darl"),
borderRadius: BorderRadius.circular(15),
),
child: Column(
children: [
const SizedBox(height: 8),
_buildSectionTitle('✨ Key Beginner Tips'),
const SizedBox(height: 8),
_buildTipPoint('Start on the Edges and Corners:',
'Numbers on the edge or corner of the board are easier to solve because they have fewer surrounding squares to check.'),
_buildTipPoint('Don\'t Guess:',
'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.'),
const SizedBox(height: 8),
],
),
),
],
),
),
);
}
}

View File

@@ -0,0 +1,209 @@
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_components/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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 SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: 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"),
],
),
),
),
],
),
)
: BuildMyScoreBoardList(),
],
),
);
}
},
);
}
}

View File

@@ -2,19 +2,14 @@ import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_ai/package_tools/ai_chat.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class MzansiAi extends StatefulWidget {
// final AppUser signedInUser;
// final String? startUpQuestion;
final MzansiAiArguments arguments;
const MzansiAi({
super.key,
required this.arguments,
// required this.signedInUser,
// this.startUpQuestion,
});
@override
@@ -22,16 +17,14 @@ class MzansiAi extends StatefulWidget {
}
class _MzansiAiState extends State<MzansiAi> {
int _selcetedIndex = 0;
MihPackageAction getAction() {
return MihPackageAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
context.read<MzansiAiProvider>().setStartUpQuestion(null);
context.goNamed(
'mihHome',
extra: widget.arguments.personalSelected,
);
FocusScope.of(context).unfocus();
},
@@ -41,23 +34,18 @@ class _MzansiAiState extends State<MzansiAi> {
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.chat)] = () {
setState(() {
_selcetedIndex = 0;
});
context.read<MzansiAiProvider>().setToolIndex(0);
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
selcetedIndex: context.watch<MzansiAiProvider>().toolIndex,
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
AiChat(
signedInUser: widget.arguments.signedInUser,
startUpQuestion: widget.arguments.startUpQuestion,
),
AiChat(),
];
return toolBodies;
}
@@ -81,12 +69,9 @@ class _MzansiAiState extends State<MzansiAi> {
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selcetedIndex,
selectedbodyIndex: context.watch<MzansiAiProvider>().toolIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
print("Index: $_selcetedIndex");
context.read<MzansiAiProvider>().setToolIndex(newValue);
},
);
}

View File

@@ -3,16 +3,13 @@ import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MzansiAiTile extends StatefulWidget {
final MzansiAiArguments arguments;
final double packageSize;
const MzansiAiTile({
super.key,
required this.arguments,
required this.packageSize,
});
@@ -27,7 +24,6 @@ class _MzansiAiTileState extends State<MzansiAiTile> {
onTap: () {
context.goNamed(
'mzansiAi',
extra: widget.arguments,
);
// Navigator.of(context).pushNamed(
// '/mzansi-ai',

View File

@@ -4,6 +4,8 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:gpt_markdown/gpt_markdown.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
@@ -14,22 +16,18 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_radio_options.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:flutter/material.dart';
import 'package:flutter_chat_ui/flutter_chat_ui.dart';
import 'package:flutter_chat_types/flutter_chat_types.dart' as types;
import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter_tts/flutter_tts.dart';
import 'package:ollama_dart/ollama_dart.dart' as ollama;
import 'package:provider/provider.dart';
import 'package:uuid/uuid.dart';
class AiChat extends StatefulWidget {
final AppUser signedInUser;
final String? startUpQuestion;
const AiChat({
super.key,
required this.signedInUser,
this.startUpQuestion,
});
@override
@@ -615,9 +613,13 @@ class _AiChatState extends State<AiChat> {
@override
void initState() {
super.initState();
MzansiAiProvider mzansiAiProvider = context.read<MzansiAiProvider>();
MzansiProfileProvider mzansiProfileProvider =
context.read<MzansiProfileProvider>();
_user = types.User(
firstName: widget.signedInUser.fname,
id: widget.signedInUser.app_id, //'82091008-a484-4a89-ae75-a22bf8d6f3ac',
firstName: mzansiProfileProvider.user!.fname,
id: mzansiProfileProvider
.user!.app_id, //'82091008-a484-4a89-ae75-a22bf8d6f3ac',
);
_mihAI = types.User(
firstName: "Mzansi AI",
@@ -634,8 +636,10 @@ class _AiChatState extends State<AiChat> {
);
initTTS();
_ttsVoiceController.addListener(voiceSelected);
if (widget.startUpQuestion != null && widget.startUpQuestion!.isNotEmpty) {
final partialText = types.PartialText(text: widget.startUpQuestion!);
if (mzansiAiProvider.startUpQuestion != null &&
mzansiAiProvider.startUpQuestion!.isNotEmpty) {
final partialText =
types.PartialText(text: mzansiAiProvider.startUpQuestion!);
WidgetsBinding.instance.addPostFrameCallback((_) {
_handleSendPressed(partialText);
});

View File

@@ -1,20 +1,17 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart';
import 'package:mzansi_innovation_hub/mih_components/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;
final String myLocation;
final String? startUpSearch;
const BuildBusinessSearchResultsList({
super.key,
required this.businessList,
required this.myLocation,
required this.startUpSearch,
});
@override
@@ -26,52 +23,48 @@ class _BuildBusinessSearchResultsListState
extends State<BuildBusinessSearchResultsList> {
@override
Widget build(BuildContext context) {
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: () {
context.goNamed(
'businessProfileView',
extra: BusinessViewArguments(
widget.businessList[index],
widget.businessList[index].Name,
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: MihBusinessProfilePreview(
business: widget.businessList[index],
),
),
);
// // Navigator.of(context).pushNamed(
// // '/business-profile/view',
// // arguments: BusinessViewArguments(
// // widget.businessList[index],
// // widget.businessList[index].Name,
// // ),
// );
},
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: MihBusinessProfilePreview(
business: widget.businessList[index],
myLocation: widget.myLocation,
),
),
),
);
},
);
},
);

View File

@@ -1,18 +1,17 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_business_profile_preview.dart';
import 'package:mzansi_innovation_hub/mih_components/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;
final String? myLocation;
const BuildFavouriteBusinessesList({
super.key,
required this.favouriteBusinesses,
required this.myLocation,
});
@override
@@ -24,54 +23,49 @@ class _BuildFavouriteBusinessesListState
extends State<BuildFavouriteBusinessesList> {
@override
Widget build(BuildContext context) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: widget.favouriteBusinesses.length,
separatorBuilder: (BuildContext context, index) {
return Divider(
color: Theme.of(context).colorScheme.secondary,
);
},
itemBuilder: (context, index) {
final Business? business = widget.favouriteBusinesses[index];
if (business == 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: () {
context.goNamed(
'businessProfileView',
extra: BusinessViewArguments(
widget.favouriteBusinesses[index]!,
widget.favouriteBusinesses[index]!.Name,
return Consumer<MzansiDirectoryProvider>(
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
Widget? child) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
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.goNamed(
'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: MihBusinessProfilePreview(
business: widget.favouriteBusinesses[index]!,
),
),
);
// Navigator.of(context).pushNamed(
// '/business-profile/view',
// arguments: BusinessViewArguments(
// business,
// business.Name,
// ),
// );
},
splashColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
.withOpacity(0.2),
borderRadius: BorderRadius.circular(15),
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 25,
),
child: MihBusinessProfilePreview(
business: business, myLocation: widget.myLocation),
),
),
);
},
);
},
);

View File

@@ -3,7 +3,9 @@ import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_personal_profile_preview.dart';
import 'package:mzansi_innovation_hub/mih_components/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;
@@ -21,45 +23,46 @@ class _BuildUserSearchResultsListState
extends State<BuildUserSearchResultsList> {
@override
Widget build(BuildContext context) {
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: () {
context.goNamed(
'mzansiProfileView',
extra: widget.userList[index],
);
// Navigator.of(context).pushNamed(
// '/mzansi-profile/view',
// arguments: widget.userList[index],
// );
},
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,
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:
MihPersonalProfilePreview(user: widget.userList[index]),
),
),
child: MihPersonalProfilePreview(
user: widget.userList[index],
),
),
),
);
},
);
},
);

View File

@@ -1,19 +1,18 @@
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_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_location_services.dart';
import 'package:provider/provider.dart';
class MzansiDirectory extends StatefulWidget {
final MzansiDirectoryArguments arguments;
const MzansiDirectory({
super.key,
required this.arguments,
});
@override
@@ -21,75 +20,56 @@ class MzansiDirectory extends StatefulWidget {
}
class _MzansiDirectoryState extends State<MzansiDirectory> {
int _selcetedIndex = 0;
late Future<Position?> futurePosition =
MIHLocationAPI().getGPSPosition(context);
Future<void> initialiseGPSLocation() async {
MzansiDirectoryProvider directoryProvider =
context.read<MzansiDirectoryProvider>();
MIHLocationAPI().getGPSPosition(context).then((position) {
directoryProvider.setUserPosition(position);
});
}
@override
void initState() {
super.initState();
if (widget.arguments.packageIndex == null) {
_selcetedIndex = 0;
} else {
_selcetedIndex = widget.arguments.packageIndex!;
}
WidgetsBinding.instance.addPostFrameCallback((_) async {
initialiseGPSLocation();
});
}
@override
Widget build(BuildContext context) {
print('MzansiDirectory build method called!');
return MihPackage(
appActionButton: getAction(),
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selcetedIndex,
selectedbodyIndex: context.watch<MzansiDirectoryProvider>().toolIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
context.read<MzansiDirectoryProvider>().setToolIndex(newValue);
},
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
FutureBuilder(
future: futurePosition,
builder: (context, asyncSnapshot) {
String myLocation = "";
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
myLocation = "Getting Your GPS Location Ready";
} else {
myLocation = asyncSnapshot.data
.toString()
.replaceAll("Latitude: ", "")
.replaceAll("Longitude: ", "");
}
return MihSearchMzansi(
personalSearch: widget.arguments.personalSearch,
myLocation: myLocation,
startSearchText: widget.arguments.startSearchText,
);
}),
List<Widget> toolBodies = [];
// String myLocation = "Getting Your GPS Location Ready";
// if (directoryProvider.userPosition != null) {
// myLocation = directoryProvider.userPosition
// .toString()
// .replaceAll("Latitude: ", "")
// .replaceAll("Longitude: ", "");
// }
toolBodies.addAll([
MihSearchMzansi(
// personalSearch: directoryProvider.personalSearch,
// startSearchText: "",
),
// MihContacts(),
FutureBuilder(
future: futurePosition,
builder: (context, asyncSnapshot) {
String myLocation = "";
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
myLocation = "Getting Your GPS Location Ready";
} else {
myLocation = asyncSnapshot.data
.toString()
.replaceAll("Latitude: ", "")
.replaceAll("Longitude: ", "");
}
return MihFavouriteBusinesses(
myLocation: myLocation,
);
}),
];
MihFavouriteBusinesses(),
]);
return toolBodies;
}
@@ -98,10 +78,13 @@ class _MzansiDirectoryState extends State<MzansiDirectory> {
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
MzansiDirectoryProvider directoryProvider =
context.read<MzansiDirectoryProvider>();
context.goNamed(
'mihHome',
extra: widget.arguments.personalSearch,
);
directoryProvider.setToolIndex(0);
directoryProvider.setPersonalSearch(true);
FocusScope.of(context).unfocus();
},
);
@@ -110,23 +93,14 @@ class _MzansiDirectoryState extends State<MzansiDirectory> {
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.search)] = () {
setState(() {
_selcetedIndex = 0;
});
context.read<MzansiDirectoryProvider>().setToolIndex(0);
};
// temp[const Icon(Icons.person)] = () {
// setState(() {
// _selcetedIndex = 1;
// });
// };
temp[const Icon(Icons.business_center)] = () {
setState(() {
_selcetedIndex = 1;
});
context.read<MzansiDirectoryProvider>().setToolIndex(1);
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
selcetedIndex: context.watch<MzansiDirectoryProvider>().toolIndex,
);
}
@@ -134,7 +108,7 @@ class _MzansiDirectoryState extends State<MzansiDirectory> {
List<String> toolTitles = [
"Mzansi Search",
"Favourite Businesses",
"Contacts",
// "Contacts",
];
return toolTitles;
}

View File

@@ -1,18 +1,15 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MzansiDirectoryTile extends StatefulWidget {
final double packageSize;
final bool personalSelected;
const MzansiDirectoryTile({
super.key,
required this.packageSize,
required this.personalSelected,
});
@override
@@ -26,10 +23,6 @@ class _MzansiDirectoryTileState extends State<MzansiDirectoryTile> {
onTap: () {
context.goNamed(
"mzansiDirectory",
extra: MzansiDirectoryArguments(
personalSearch: widget.personalSelected,
startSearchText: null,
),
);
// Navigator.of(context).pushNamed(
// '/mzansi-directory',

View File

@@ -1,24 +1,22 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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_favourite_businesses_list.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:supertokens_flutter/supertokens.dart';
import 'package:provider/provider.dart';
class MihFavouriteBusinesses extends StatefulWidget {
final String? myLocation;
const MihFavouriteBusinesses({
super.key,
required this.myLocation,
});
@override
@@ -29,42 +27,42 @@ class _MihFavouriteBusinessesState extends State<MihFavouriteBusinesses> {
final TextEditingController businessSearchController =
TextEditingController();
final FocusNode searchFocusNode = FocusNode();
late Future<List<BookmarkedBusiness>> boookmarkedBusinessListFuture;
List<BookmarkedBusiness> listBookmarkedBusinesses = [];
final ValueNotifier<List<Business?>> searchBookmarkedBusinesses =
ValueNotifier([]);
late Future<Map<String, Business?>> businessDetailsMapFuture;
Map<String, Business?> _businessDetailsMap = {};
Timer? _debounce;
Future<Map<String, Business?>>
getAndMapAllBusinessDetailsForBookmarkedBusinesses() async {
String user_id = await SuperTokens.getUserId();
List<BookmarkedBusiness> bookmarked = await MihMzansiDirectoryServices()
.getAllUserBookmarkedBusiness(user_id);
listBookmarkedBusinesses = bookmarked;
Future<void> getAndMapAllBusinessDetailsForBookmarkedBusinesses(
MzansiProfileProvider mzansiProfileProvider,
MzansiDirectoryProvider directoryProvider,
) async {
await MihMzansiDirectoryServices().getAllUserBookmarkedBusiness(
mzansiProfileProvider.user!.app_id,
directoryProvider,
);
Map<String, Business?> businessMap = {};
List<Future<Business?>> detailFutures = [];
for (var item in bookmarked) {
for (var item in directoryProvider.bookmarkedBusinesses) {
detailFutures.add(MihBusinessDetailsServices()
.getBusinessDetailsByBusinessId(item.business_id));
}
List<Business?> details = await Future.wait(detailFutures);
for (int i = 0; i < bookmarked.length; i++) {
businessMap[bookmarked[i].business_id] = details[i];
for (int i = 0; i < directoryProvider.bookmarkedBusinesses.length; i++) {
businessMap[directoryProvider.bookmarkedBusinesses[i].business_id] =
details[i];
}
_businessDetailsMap = businessMap;
_filterAndSetBusinesses();
return businessMap;
directoryProvider.setBusinessDetailsMap(detailsMap: businessMap);
_filterAndSetBusinesses(directoryProvider);
}
void _filterAndSetBusinesses() {
void _filterAndSetBusinesses(MzansiDirectoryProvider directoryProvider) {
List<Business?> businessesToDisplay = [];
String query = businessSearchController.text.toLowerCase();
for (var bookmarked in listBookmarkedBusinesses) {
for (var bookmarked in directoryProvider.bookmarkedBusinesses) {
if (bookmarked.business_name.toLowerCase().contains(query)) {
if (_businessDetailsMap.containsKey(bookmarked.business_id)) {
businessesToDisplay.add(_businessDetailsMap[bookmarked.business_id]);
if (directoryProvider.businessDetailsMap
.containsKey(bookmarked.business_id)) {
businessesToDisplay.add(
directoryProvider.businessDetailsMap[bookmarked.business_id]);
}
}
}
@@ -82,14 +80,21 @@ class _MihFavouriteBusinessesState extends State<MihFavouriteBusinesses> {
@override
void initState() {
super.initState();
businessDetailsMapFuture =
getAndMapAllBusinessDetailsForBookmarkedBusinesses();
MzansiDirectoryProvider directoryProvider =
context.read<MzansiDirectoryProvider>();
MzansiProfileProvider mzansiProfileProvider =
context.read<MzansiProfileProvider>();
getAndMapAllBusinessDetailsForBookmarkedBusinesses(
mzansiProfileProvider,
directoryProvider,
);
businessSearchController.addListener(() {
if (_debounce?.isActive ?? false) {
_debounce!.cancel();
}
_debounce = Timer(const Duration(milliseconds: 200), () {
_filterAndSetBusinesses();
_filterAndSetBusinesses(directoryProvider);
});
});
}
@@ -123,141 +128,95 @@ class _MihFavouriteBusinessesState extends State<MihFavouriteBusinesses> {
),
),
const SizedBox(height: 10),
FutureBuilder<Map<String, Business?>>(
future: businessDetailsMapFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Mihloadingcircle(
message: "Getting your favourites",
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 (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
// No need to re-filter here, _filterAndSetBusinesses is called in initState
// and by the text controller listener.
return ValueListenableBuilder<List<Business?>>(
valueListenable:
searchBookmarkedBusinesses, // Listen to changes in this
builder: (context, businesses, child) {
// Display message if no results after search
if (businesses.isEmpty &&
businessSearchController.text.isNotEmpty) {
return Column(
children: [
const SizedBox(height: 50),
Icon(
MihIcons.iDontKnow,
size: 165,
} else if (filteredBusinesses.isEmpty &&
businessSearchController.text.isEmpty) {
return 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(
"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"),
),
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 BuildFavouriteBusinessesList(
favouriteBusinesses:
businesses, // Pass the filtered list from ValueNotifier
myLocation: widget.myLocation,
);
},
);
} else {
// This block handles the case where there are no bookmarked businesses initially
return 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(
"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"),
children: [
TextSpan(text: "Use the mzansi search"),
TextSpan(
text:
" to find your favourite businesses of mzansi"),
],
),
),
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"),
// WidgetSpan(
// alignment:
// PlaceholderAlignment.middle,
// child: Icon(
// Icons.search,
// size: 20,
// color:
// MzansiInnovationHub.of(context)!
// .theme
// .secondaryColor(),
// ),
// ),
TextSpan(
text:
" to find your favourite businesses of mzansi"),
],
),
),
),
],
),
);
}
} else if (snapshot.hasError) {
return Center(
child: Text(
"Error loading bookmarked businesses: ${snapshot.error}"), // Show specific error
);
} else {
// Fallback for unexpected states
return Center(
child: Text("An unknown error occurred."),
),
],
),
);
}
return BuildFavouriteBusinessesList(
favouriteBusinesses: filteredBusinesses,
);
}),
],
),

View File

@@ -1,4 +1,5 @@
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_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
@@ -9,22 +10,19 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_search_bar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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_user_services.dart';
import 'package:provider/provider.dart';
class MihSearchMzansi extends StatefulWidget {
final bool personalSearch;
final String? myLocation;
final String? startSearchText;
const MihSearchMzansi({
super.key,
required this.personalSearch,
required this.myLocation,
required this.startSearchText,
});
@override
@@ -35,80 +33,89 @@ 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();
Future<List<Business>?> futureBusinessSearchResults = Future.value();
// 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;
void swapPressed() {
Future<void> swapPressed(MzansiProfileProvider profileProvider,
MzansiDirectoryProvider directoryProvider) async {
directoryProvider.setPersonalSearch(!directoryProvider.personalSearch);
setState(() {
userSearch = !userSearch;
if (filterOn) {
filterOn = !filterOn;
}
});
if (businessTypeController.text.isNotEmpty) {
setState(() {
futureBusinessSearchResults = Future.value();
businessTypeController.clear();
});
}
searchPressed();
await searchPressed(profileProvider, directoryProvider);
}
void clearAll() {
void clearAll(MzansiDirectoryProvider directoryProvider) {
directoryProvider.setSearchedBusinesses(searchedBusinesses: []);
directoryProvider.setSearchedUsers(searchedUsers: []);
directoryProvider.setSearchTerm(searchTerm: "");
setState(() {
futureUserSearchResults = Future.value();
futureBusinessSearchResults = Future.value();
mzansiSearchController.clear();
businessTypeController.clear();
});
}
void searchPressed() {
Future<void> searchPressed(MzansiProfileProvider profileProvider,
MzansiDirectoryProvider directoryProvider) async {
setState(() {
// userSearch = !userSearch;
if (userSearch && mzansiSearchController.text.isNotEmpty) {
futureUserSearchResults =
MihUserServices().searchUsers(mzansiSearchController.text, context);
} else {
if (
// mzansiSearchController.text.isNotEmpty &&
businessTypeController.text.isNotEmpty) {
futureBusinessSearchResults = MihBusinessDetailsServices()
.searchBusinesses(mzansiSearchController.text,
businessTypeController.text, context);
} else if (mzansiSearchController.text.isNotEmpty) {
futureBusinessSearchResults = MihBusinessDetailsServices()
.searchBusinesses(mzansiSearchController.text,
businessTypeController.text, context);
}
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);
directoryProvider.setSearchedUsers(searchedUsers: userResults);
} 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);
}
directoryProvider.setSearchedBusinesses(
searchedBusinesses: businessSearchResults);
}
setState(() {
loadingSearchResults = false;
});
}
@override
void dispose() {
super.dispose();
businessTypeController.dispose();
mzansiSearchController.dispose();
}
@override
void initState() {
super.initState();
setState(() {
userSearch = widget.personalSearch;
availableBusinessTypes =
MihBusinessDetailsServices().fetchAllBusinessTypes();
if (widget.startSearchText != null) {
mzansiSearchController.text = widget.startSearchText!;
searchPressed();
} else {
mzansiSearchController.text = "";
}
MzansiDirectoryProvider directoryProvider =
context.read<MzansiDirectoryProvider>();
availableBusinessTypes =
MihBusinessDetailsServices().fetchAllBusinessTypes();
mzansiSearchController.text = "";
WidgetsBinding.instance.addPostFrameCallback((_) async {
directoryProvider.setSearchedUsers(searchedUsers: []);
});
}
@@ -123,444 +130,427 @@ class _MihSearchMzansiState extends State<MihSearchMzansi> {
}
Widget getBody(double width) {
return MihSingleChildScroll(
child: Column(
children: [
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: userSearch ? Icons.person : Icons.business,
suffixTools: [
IconButton(
onPressed: () {
swapPressed();
},
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();
},
onClearIconTap: () {
clearAll();
},
searchFocusNode: searchFocusNode,
),
),
Visibility(
visible: !userSearch,
child: const SizedBox(width: 10),
),
Visibility(
visible: !userSearch,
child: IconButton(
onPressed: () {
if (filterOn) {
clearAll();
}
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();
} else {
MihAlertServices().errorAlert(
"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(
return Consumer2<MzansiProfileProvider, MzansiDirectoryProvider>(
builder: (BuildContext context, MzansiProfileProvider profileProvider,
MzansiDirectoryProvider directoryProvider, Widget? child) {
return MihSingleChildScroll(
child: Column(
children: [
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"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
],
],
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,
),
),
),
);
}),
const SizedBox(height: 10),
displaySearchResults(userSearch, widget.myLocation ?? ""),
],
),
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().errorAlert(
"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),
displaySearchResults(directoryProvider),
],
),
);
},
);
}
Widget displaySearchResults(bool userSearch, String myLocation) {
if (userSearch) {
return FutureBuilder(
future: futureUserSearchResults,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Mihloadingcircle();
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData &&
snapshot.requireData!.isNotEmpty) {
// return Text("Pulled Data successfully");
snapshot.requireData!
.sort((a, b) => a.username.compareTo(b.username));
return Column(
children: [
Text(
"People of Mzansi",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
BuildUserSearchResultsList(userList: snapshot.requireData!),
],
);
} else if (!snapshot.hasData) {
return 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,
Widget displayBusinessSearchResults(
MzansiDirectoryProvider directoryProvider) {
KenLogger.success(
"Searched Businesses: ${directoryProvider.searchedBusinesses}");
if (directoryProvider.searchedBusinesses == null || 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 Column(
children: [
Text(
"Businesses of Mzansi",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
BuildBusinessSearchResultsList(
businessList: directoryProvider.searchedBusinesses!,
),
],
);
} else if (directoryProvider.searchedBusinesses!.isEmpty &&
directoryProvider.searchTerm.isNotEmpty) {
// return Text("Pulled Data successfully");
return 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 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"),
),
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"),
],
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"),
),
),
),
],
),
);
// return 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(
// "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"),
// ),
// ),
// ],
// );
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData &&
snapshot.requireData!.isEmpty) {
// return Text("Pulled Data successfully");
return Column(
children: [
const SizedBox(height: 50),
Icon(
MihIcons.iDontKnow,
size: 165,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
TextSpan(text: " to search for people of Mzansi"),
],
),
const SizedBox(height: 10),
Text(
"Let's try refining your search",
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
),
),
const SizedBox(height: 10),
Center(
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
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/${mzansiSearchController.text}",
style: TextStyle(
fontSize: 25,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
textAlign: TextAlign.center,
),
);
}
},
),
],
),
);
} else {
return FutureBuilder(
future: futureBusinessSearchResults,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Mihloadingcircle();
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData &&
snapshot.requireData!.isNotEmpty) {
// return Text("Pulled Data successfully");
snapshot.requireData!.sort((a, b) => a.Name.compareTo(b.Name));
return Column(
children: [
Text(
"Businesses of Mzansi",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
BuildBusinessSearchResultsList(
businessList: snapshot.requireData!,
myLocation: myLocation,
startUpSearch: mzansiSearchController.text,
),
],
);
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData &&
snapshot.requireData!.isEmpty) {
// return Text("Pulled Data successfully");
return Column(
children: [
const SizedBox(height: 50),
Icon(
MihIcons.iDontKnow,
size: 165,
color: 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 (!snapshot.hasData) {
return 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/${mzansiSearchController.text}",
style: TextStyle(
fontSize: 25,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")),
textAlign: TextAlign.center,
),
);
}
},
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 (directoryProvider.searchedUsers == null || loadingSearchResults) {
return Center(
child: const Mihloadingcircle(),
);
} else if (directoryProvider.searchedUsers!.isNotEmpty) {
// return Text("Pulled Data successfully");
directoryProvider.searchedUsers!
.sort((a, b) => a.username.compareTo(b.username));
return Column(
children: [
Text(
"People of Mzansi",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
BuildUserSearchResultsList(
userList: directoryProvider.searchedUsers!),
],
);
} else if (directoryProvider.searchedUsers!.isEmpty &&
directoryProvider.searchTerm.isEmpty) {
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 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 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,
),
);
}
}
Widget displaySearchResults(MzansiDirectoryProvider directoryProvider) {
if (directoryProvider.personalSearch) {
return displayPersonalSearchResults(directoryProvider);
} else {
return displayBusinessSearchResults(directoryProvider);
}
}
}

View File

@@ -1,34 +1,15 @@
import 'dart:convert';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.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_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart';
import 'package:mzansi_innovation_hub/mih_components/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:supertokens_flutter/http.dart' as http;
import 'package:provider/provider.dart';
class BuildEmployeeList extends StatefulWidget {
final List<BusinessEmployee> employees;
final BusinessArguments arguments;
const BuildEmployeeList({
super.key,
required this.employees,
required this.arguments,
});
@override
@@ -36,369 +17,57 @@ class BuildEmployeeList extends StatefulWidget {
}
class _BuildEmployeeListState extends State<BuildEmployeeList> {
TextEditingController accessController = TextEditingController();
TextEditingController typeController = TextEditingController();
TextEditingController fnameController = TextEditingController();
TextEditingController lnameController = TextEditingController();
final _formKey = GlobalKey<FormState>();
final baseAPI = AppEnviroment.baseApiUrl;
Future<void> updateEmployeeAPICall(int index) async {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
var response = await http.put(
Uri.parse("$baseAPI/business-user/employees/update/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"business_id": widget.employees[index].business_id,
"app_id": widget.employees[index].app_id,
"title": typeController.text,
"access": accessController.text,
}),
);
if (response.statusCode == 200) {
// Navigator.of(context).pop();
// Navigator.of(context).pop();
// Navigator.of(context).pop();
// //setState(() {});
// Navigator.of(context).pushNamed(
// '/business-profile/manage',
// arguments: BusinessArguments(
// widget.arguments.signedInUser,
// widget.arguments.businessUser,
// widget.arguments.business,
// ),
// );
String message = "Your employees details have been updated.";
successPopUp(message, false);
} else {
internetConnectionPopUp();
}
}
Future<void> deleteNoteApiCall(int index) async {
var response = await http.delete(
Uri.parse("$baseAPI/business-user/employees/delete/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"business_id": widget.employees[index].business_id,
"app_id": widget.employees[index].app_id,
}),
);
//print("Here4");
//print(response.statusCode);
if (response.statusCode == 200) {
// Navigator.of(context).pop();
// Navigator.of(context).pop();
// Navigator.of(context).pop();
// Navigator.of(context).pushNamed(
// '/business-profile/manage',
// arguments: BusinessArguments(
// widget.arguments.signedInUser,
// widget.arguments.businessUser,
// widget.arguments.business,
// ),
// );
String message =
"The employee has been deleted successfully. This means they will no longer have access to your business profile";
successPopUp(message, false);
} else {
internetConnectionPopUp();
}
}
void successPopUp(String message, bool stayOnPersonalSide) {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.check_circle_outline_rounded,
size: 150,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Successfully Updated Profile",
alertBody: Column(
children: [
Text(
message,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.goNamed(
'mihHome',
extra: stayOnPersonalSide,
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
elevation: 10,
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
// return MIHSuccessMessage(
// successType: "Success",
// successMessage: message,
// );
},
);
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
bool isRequiredFieldsCaptured() {
if (accessController.text.isEmpty || typeController.text.isEmpty) {
return false;
} else {
return true;
}
}
void updateEmployeePopUp(int index, double width) {
setState(() {
accessController.text = widget.employees[index].access;
typeController.text = widget.employees[index].title;
fnameController.text = widget.employees[index].fname;
lnameController.text = widget.employees[index].lname;
});
void updateEmployeePopUp(BusinessEmployee employee) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => 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(index);
},
),
],
onWindowTapClose: () {
Navigator.pop(context);
},
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: 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: typeController,
multiLineInput: false,
requiredText: true,
readOnly: true,
hintText: "Title",
),
// MihDropdownField(
// controller: typeController,
// hintText: "Title",
// dropdownOptions: const ["Doctor", "Assistant", "Other"],
// editable: true,
// enableSearch: true,
// validator: (value) {
// return MihValidationServices().isEmpty(value);
// },
// requiredText: true,
// ),
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(index);
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(
errorType: "Input Error");
},
);
}
} else {
MihAlertServices().formNotFilledCompletely(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,
),
),
),
),
],
),
],
),
),
builder: (context) => MihEditEmployeeDetailsWindow(
employee: employee,
),
);
}
void showDeleteWarning(int index) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MIHDeleteMessage(
deleteType: "Employee",
onTap: () {
deleteNoteApiCall(index);
}));
}
@override
void dispose() {
accessController.dispose();
typeController.dispose();
fnameController.dispose();
lnameController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
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.employees.length,
itemBuilder: (context, index) {
//final patient = widget.patients[index].id_no.contains(widget.searchString);
//print(index);
var isMe = "";
if (widget.arguments.signedInUser.app_id ==
widget.employees[index].app_id) {
isMe = "(You)";
}
return ListTile(
title: Text(
"${widget.employees[index].fname} ${widget.employees[index].lname} - ${widget.employees[index].title} $isMe"),
subtitle: Text(
"${widget.employees[index].username}\n${widget.employees[index].email}\nAccess: ${widget.employees[index].access}",
style: TextStyle(
return Consumer<MzansiProfileProvider>(
builder: (BuildContext context,
MzansiProfileProvider mzansiProfileProvider, Widget? child) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
onTap: () {
updateEmployeePopUp(index, screenWidth);
);
},
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);
},
);
},
);
},

View File

@@ -1,32 +1,14 @@
import 'dart:convert';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/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_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_add_employee_window.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:flutter/material.dart';
import 'package:supertokens_flutter/http.dart' as http;
import 'package:provider/provider.dart';
class BuildUserList extends StatefulWidget {
final List<AppUser> users;
final BusinessArguments arguments;
const BuildUserList({
super.key,
required this.users,
required this.arguments,
});
@override
@@ -34,314 +16,61 @@ class BuildUserList extends StatefulWidget {
}
class _BuildUserListState extends State<BuildUserList> {
TextEditingController accessController = TextEditingController();
TextEditingController typeController = TextEditingController();
TextEditingController usernameController = TextEditingController();
TextEditingController emailController = TextEditingController();
final _formKey = GlobalKey<FormState>();
final baseAPI = AppEnviroment.baseApiUrl;
Future<void> createBusinessUserAPICall(int index) async {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
var response = await http.post(
Uri.parse("$baseAPI/business-user/insert/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"business_id": widget.arguments.business!.business_id,
"app_id": widget.users[index].app_id,
"signature": "",
"sig_path": "",
"title": "",
"access": accessController.text,
}),
);
if (response.statusCode == 201) {
// Navigator.of(context).pop();
// Navigator.of(context).pop();
// Navigator.of(context).pop();
// Navigator.of(context).pushNamed(
// '/business-profile/manage',
// arguments: BusinessArguments(
// widget.arguments.signedInUser,
// widget.arguments.businessUser,
// widget.arguments.business,
// ),
// );
String message =
"${widget.users[index].username} is now apart of your team with ${accessController.text} access to ${widget.arguments.business!.Name}";
successPopUp(message, false);
} else {
internetConnectionPopUp();
}
}
void successPopUp(String message, bool stayOnPersonalSide) {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.check_circle_outline_rounded,
size: 150,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Successfully Updated Profile",
alertBody: Column(
children: [
Text(
message,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.goNamed(
'mihHome',
extra: stayOnPersonalSide,
);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
elevation: 10,
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
// return MIHSuccessMessage(
// successType: "Success",
// successMessage: message,
// );
},
);
}
bool isRequiredFieldsCaptured() {
if (accessController.text.isEmpty) {
return false;
} else {
return true;
}
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
String hideEmail(String email) {
var firstLetter = email[0];
var end = email.split("@")[1];
return "$firstLetter********@$end";
}
void addEmployeePopUp(int index, double width) {
setState(() {
//accessController.text = widget.users[index].access;
//typeController.text = widget.users[index].title;
// var fnameInitial = widget.users[index].fname[0];
// var lnameInitial = widget.users[index].lname[0];
usernameController.text = widget.users[index].username;
emailController.text = hideEmail(widget.users[index].email);
});
void addEmployeePopUp(
MzansiProfileProvider profileProvider, int index, double width) {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MihPackageWindow(
fullscreen: false,
windowTitle: "Add Employee",
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: 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),
// 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,
// readOnly: true,
// hintText: "Title",
// ),
// MihDropdownField(
// controller: typeController,
// hintText: "Title",
// dropdownOptions: const ["Doctor", "Assistant", "Other"],
// editable: true,
// enableSearch: true,
// validator: (value) {
// return MihValidationServices().isEmpty(value);
// },
// requiredText: true,
// ),
// 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(index);
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(
errorType: "Input Error");
},
);
}
} else {
MihAlertServices()
.formNotFilledCompletely(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);
}));
}
@override
void dispose() {
accessController.dispose();
typeController.dispose();
usernameController.dispose();
emailController.dispose();
super.dispose();
context: context,
barrierDismissible: false,
builder: (context) => MihAddEmployeeWindow(
user: profileProvider.userSearchResults[index],
),
);
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
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.users.length,
itemBuilder: (context, index) {
var isYou = "";
if (widget.arguments.signedInUser.app_id ==
widget.users[index].app_id) {
isYou = "(You)";
}
return ListTile(
title: Text("@${widget.users[index].username} $isYou"),
subtitle: Text(
"Email: ${hideEmail(widget.users[index].email)}",
style: TextStyle(
return Consumer<MzansiProfileProvider>(
builder: (BuildContext context, MzansiProfileProvider profileProvider,
Widget? child) {
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
separatorBuilder: (BuildContext context, index) {
return Divider(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
),
onTap: () {
addEmployeePopUp(index, screenWidth);
);
},
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);
},
);
},
);
},

View File

@@ -1,21 +1,23 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/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_directory_services.dart';
import 'package:supertokens_flutter/supertokens.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
@@ -23,16 +25,16 @@ class MihAddBookmarkAlert extends StatefulWidget {
}
class _MihAddBookmarkAlertState extends State<MihAddBookmarkAlert> {
Future<void> addBookmark(String business_id) async {
Future<void> addBookmark(
MzansiProfileProvider profileProvider, String business_id) async {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
String user_id = await SuperTokens.getUserId();
await MihMzansiDirectoryServices()
.addBookmarkedBusiness(user_id, business_id)
.addBookmarkedBusiness(profileProvider.user!.app_id, business_id)
.then((statusCode) {
context.pop();
if (statusCode == 201) {
@@ -77,14 +79,9 @@ class _MihAddBookmarkAlertState extends State<MihAddBookmarkAlert> {
Center(
child: MihButton(
onPressed: () {
context.goNamed(
"mzansiDirectory",
extra: MzansiDirectoryArguments(
personalSearch: false,
startSearchText: widget.business.Name,
packageIndex: 1,
),
);
widget.onSuccessDismissPressed!.call();
context.pop();
context.pop();
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
@@ -117,69 +114,76 @@ class _MihAddBookmarkAlertState extends State<MihAddBookmarkAlert> {
@override
Widget build(BuildContext context) {
return MihPackageAlert(
alertColour: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
alertIcon: Icon(
Icons.warning_rounded,
size: 100,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Bookmark Business",
alertBody: Column(
children: [
Text(
"Are you sure you want to save ${widget.business.Name} to your Mzansi Directory?",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
),
return Consumer<MzansiProfileProvider>(
builder: (BuildContext context, MzansiProfileProvider profileProvider,
Widget? child) {
return MihPackageAlert(
alertColour: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
alertIcon: Icon(
Icons.warning_rounded,
size: 100,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
const SizedBox(height: 25),
Wrap(
spacing: 10,
runSpacing: 10,
alertTitle: "Bookmark Business",
alertBody: Column(
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,
),
Text(
"Are you sure you want to save ${widget.business.Name} to your Mzansi Directory?",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
),
),
MihButton(
width: 300,
onPressed: () {
addBookmark(widget.business.business_id);
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
child: Text(
"Bookmark Business",
style: TextStyle(
color: MihColors.getPrimaryColor(
const SizedBox(height: 25),
Wrap(
spacing: 10,
runSpacing: 10,
children: [
MihButton(
width: 300,
onPressed: () async {
Navigator.of(context).pop();
},
buttonColor: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
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,
),
),
),
],
),
],
),
],
),
);
},
);
}
}

View File

@@ -0,0 +1,250 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/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 {
internetConnectionPopUp();
}
}
void successPopUp(String message, bool stayOnPersonalSide) {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.check_circle_outline_rounded,
size: 150,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Successfully Updated Profile",
alertBody: Column(
children: [
Text(
message,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.pop();
context.pop();
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
elevation: 10,
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
// return MIHSuccessMessage(
// successType: "Success",
// successMessage: message,
// );
},
);
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
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 {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(
errorType: "Input Error");
},
);
}
} else {
MihAlertServices().formNotFilledCompletely(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);
},
);
},
);
}
}

View File

@@ -7,23 +7,24 @@ import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_review
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_add_bookmark_alert.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_delete_bookmark_alert.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_review_business_window.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart';
import 'package:provider/provider.dart';
import 'package:redacted/redacted.dart';
import 'package:supertokens_flutter/supertokens.dart';
import 'package:url_launcher/url_launcher.dart';
class MihBusinessCard extends StatefulWidget {
final Business business;
final String? startUpSearch;
final double width;
const MihBusinessCard({
super.key,
required this.business,
required this.startUpSearch,
required this.width,
});
@@ -409,274 +410,292 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
@override
Widget build(BuildContext context) {
// double screenWidth = MediaQuery.of(context).size.width;
return Material(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
.withValues(alpha: 0.6),
borderRadius: BorderRadius.circular(25),
elevation: 10,
shadowColor: Colors.black,
child: Container(
decoration: BoxDecoration(
return Consumer<MzansiDirectoryProvider>(
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
Widget? child) {
return Material(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
borderRadius: BorderRadius.circular(10),
),
child: Column(
children: [
const SizedBox(height: 10),
_buildContactInfo(
"Call",
"Give us a quick call.",
Icons.phone,
MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark")
.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"),
false,
() {
// print("Calling ${widget.cellNumber}");
_makePhoneCall(widget.business.contact_no);
},
borderRadius: BorderRadius.circular(10),
),
Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
_buildContactInfo(
"Email",
"Send us an email.",
Icons.email,
MihColors.getPinkColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
false,
() {
// print("Emailing ${widget.email}");
_launchEmail(
widget.business.bus_email,
"Inquiery about ${widget.business.Name}",
"Dear ${widget.business.Name},\n\nI would like to inquire about your services.\n\nBest regards,\n",
);
},
),
Visibility(
visible: isValidGps(widget.business.gps_location),
child: Column(
children: [
Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
child: Column(
children: [
const SizedBox(height: 10),
_buildContactInfo(
"Call",
"Give us a quick call.",
Icons.phone,
MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
false,
() {
// print("Calling ${widget.cellNumber}");
_makePhoneCall(widget.business.contact_no);
},
),
Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
_buildContactInfo(
"Email",
"Send us an email.",
Icons.email,
MihColors.getPinkColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
false,
() {
// print("Emailing ${widget.email}");
_launchEmail(
widget.business.bus_email,
"Inquiery about ${widget.business.Name}",
"Dear ${widget.business.Name},\n\nI would like to inquire about your services.\n\nBest regards,\n",
);
},
),
Visibility(
visible: isValidGps(widget.business.gps_location),
child: Column(
children: [
Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
_buildContactInfo(
"Location",
"Come visit us.",
Icons.location_on,
MihColors.getOrangeColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
false,
() {
final latitude = double.parse(
widget.business.gps_location.split(',')[0]);
final longitude = double.parse(
widget.business.gps_location.split(',')[1]);
_launchGoogleMapsWithUrl(
latitude: latitude,
longitude: longitude,
);
},
),
],
),
_buildContactInfo(
"Location",
"Come visit us.",
Icons.location_on,
MihColors.getOrangeColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
false,
() {
final latitude = double.parse(
widget.business.gps_location.split(',')[0]);
final longitude = double.parse(
widget.business.gps_location.split(',')[1]);
_launchGoogleMapsWithUrl(
latitude: latitude,
longitude: longitude,
),
Visibility(
visible: widget.business.website.isNotEmpty &&
widget.business.website != "",
child: Column(
children: [
Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
_buildContactInfo(
"Website",
"Find out more about us.",
Icons.vpn_lock,
MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
false,
() {
_launchWebsite(widget.business.website);
},
),
],
),
),
FutureBuilder(
future: _businessReviewFuture,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState ==
ConnectionState.waiting) {
// return const SizedBox.shrink();
return Column(
children: [
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 10.0),
child: Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
Container(
child: _buildContactInfo(
"Loading Rating",
"Loading your rating.",
Icons.star_rate_rounded,
MihColors.getYellowColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
true,
null,
),
).redacted(context: context, redact: true),
],
);
},
),
],
),
} else {
BusinessReview? businessReview = asyncSnapshot.data;
String ratingDisplayTitle = "";
if (businessReview == null) {
ratingDisplayTitle = "Rate Us";
} else {
ratingDisplayTitle = "Update Rating";
}
return Column(
children: [
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 10.0),
child: Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
_buildContactInfo(
ratingDisplayTitle,
"Let us know how we are doing.",
Icons.star_rate_rounded,
MihColors.getYellowColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
false,
() {
businessReviewRatingWindow(directoryProvider,
businessReview, true, widget.width);
},
),
],
);
}
},
),
FutureBuilder(
future: _bookmarkedBusinessFuture,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState ==
ConnectionState.waiting) {
// return const SizedBox.shrink();
return Column(
children: [
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 10.0),
child: Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
Container(
child: _buildContactInfo(
"Loading Bookmark",
"Loading your bookmark.",
Icons.bookmark_add_rounded,
MihColors.getBluishPurpleColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
true,
null,
),
),
],
);
} else {
BookmarkedBusiness? bookmarkBusiness = asyncSnapshot.data;
String bookmarkDisplayTitle = "";
if (bookmarkBusiness == null) {
bookmarkDisplayTitle = "Bookmark Us";
} else {
bookmarkDisplayTitle = "Remove Bookmark";
}
return Column(
children: [
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 10.0),
child: Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
_buildContactInfo(
bookmarkDisplayTitle,
"Save us for later.",
bookmarkBusiness == null
? Icons.bookmark_add_rounded
: Icons.bookmark_remove_rounded,
MihColors.getBluishPurpleColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
false,
() {
// _launchWebsite(widget.website);
if (bookmarkBusiness == null) {
showAddBookmarkAlert();
} else {
showDeleteBookmarkAlert(bookmarkBusiness);
}
},
),
],
);
}
},
),
// Padding(
// padding: const EdgeInsets.symmetric(horizontal: 10.0),
// child: Divider(
// color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
// _buildContactInfo(
// "Bookmark",
// "Save us for later.",
// Icons.bookmark_add_rounded,
// MihColors.getBluishPurpleColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// () {
// // _launchWebsite(widget.website);
// print("Saving ${widget.business.Name} to Directory");
// showBookmarkAlert();
// },
// ),
const SizedBox(height: 10),
// Padding(
// padding: const EdgeInsets.symmetric(horizontal: 10.0),
// child: Divider(
// color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
],
),
Visibility(
visible: widget.business.website.isNotEmpty &&
widget.business.website != "",
child: Column(
children: [
Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
_buildContactInfo(
"Website",
"Find out more about us.",
Icons.vpn_lock,
MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
false,
() {
_launchWebsite(widget.business.website);
},
),
],
),
),
FutureBuilder(
future: _businessReviewFuture,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
// return const SizedBox.shrink();
return Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
Container(
child: _buildContactInfo(
"Loading Rating",
"Loading your rating.",
Icons.star_rate_rounded,
MihColors.getYellowColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
true,
null,
),
).redacted(context: context, redact: true),
],
);
} else {
BusinessReview? businessReview = asyncSnapshot.data;
String ratingDisplayTitle = "";
if (businessReview == null) {
ratingDisplayTitle = "Rate Us";
} else {
ratingDisplayTitle = "Update Rating";
}
return Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
_buildContactInfo(
ratingDisplayTitle,
"Let us know how we are doing.",
Icons.star_rate_rounded,
MihColors.getYellowColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
false,
() {
businessReviewRatingWindow(
businessReview, true, widget.width);
},
),
],
);
}
},
),
FutureBuilder(
future: _bookmarkedBusinessFuture,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState == ConnectionState.waiting) {
// return const SizedBox.shrink();
return Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
Container(
child: _buildContactInfo(
"Loading Bookmark",
"Loading your bookmark.",
Icons.bookmark_add_rounded,
MihColors.getBluishPurpleColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
true,
null,
),
),
],
);
} else {
BookmarkedBusiness? bookmarkBusiness = asyncSnapshot.data;
String bookmarkDisplayTitle = "";
if (bookmarkBusiness == null) {
bookmarkDisplayTitle = "Bookmark Us";
} else {
bookmarkDisplayTitle = "Remove Bookmark";
}
return Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: Divider(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
_buildContactInfo(
bookmarkDisplayTitle,
"Save us for later.",
bookmarkBusiness == null
? Icons.bookmark_add_rounded
: Icons.bookmark_remove_rounded,
MihColors.getBluishPurpleColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
false,
() {
// _launchWebsite(widget.website);
if (bookmarkBusiness == null) {
showAddBookmarkAlert();
} else {
showDeleteBookmarkAlert(bookmarkBusiness);
}
},
),
],
);
}
},
),
// Padding(
// padding: const EdgeInsets.symmetric(horizontal: 10.0),
// child: Divider(
// color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
// _buildContactInfo(
// "Bookmark",
// "Save us for later.",
// Icons.bookmark_add_rounded,
// MihColors.getBluishPurpleColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// () {
// // _launchWebsite(widget.website);
// print("Saving ${widget.business.Name} to Directory");
// showBookmarkAlert();
// },
// ),
const SizedBox(height: 10),
// Padding(
// padding: const EdgeInsets.symmetric(horizontal: 10.0),
// child: Divider(
// color: MihColors.getPrimaryColor(MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
// ),
// ),
],
),
),
),
);
},
);
}
Future<void> businessReviewRatingWindow(
BusinessReview? myReview, bool previouslyRated, double width) async {
MzansiDirectoryProvider directoryProvider,
BusinessReview? myReview,
bool previouslyRated,
double width) async {
if (_isUserSignedIn) {
showDialog(
context: context,
@@ -685,6 +704,17 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
businessReview: myReview,
screenWidth: width,
readOnly: false,
onSuccessDismissPressed: () async {
List<Business>? businessSearchResults = [];
businessSearchResults = await MihBusinessDetailsServices()
.searchBusinesses(directoryProvider.searchTerm,
directoryProvider.businessTypeFilter, context);
directoryProvider.setSearchedBusinesses(
searchedBusinesses: businessSearchResults);
setState(() {
_businessReviewFuture = getUserReview();
});
},
),
);
} else {
@@ -698,6 +728,11 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
context: context,
builder: (context) => MihAddBookmarkAlert(
business: widget.business,
onSuccessDismissPressed: () {
setState(() {
_bookmarkedBusinessFuture = getUserBookmark();
});
},
),
);
} else {
@@ -712,7 +747,12 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
builder: (context) => MihDeleteBookmarkAlert(
business: widget.business,
bookmarkBusiness: bookmarkBusiness,
startUpSearch: widget.startUpSearch,
onSuccessDismissPressed: () {
setState(() {
_bookmarkedBusinessFuture = getUserBookmark();
});
},
// startUpSearch: widget.startUpSearch,
));
} else {
showSignInRequiredAlert();

View File

@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/bookmarked_business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
@@ -14,12 +13,14 @@ import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services
class MihDeleteBookmarkAlert extends StatefulWidget {
final Business business;
final BookmarkedBusiness? bookmarkBusiness;
final String? startUpSearch;
final void Function()? onSuccessDismissPressed;
// final String? startUpSearch;
const MihDeleteBookmarkAlert({
super.key,
required this.business,
required this.bookmarkBusiness,
required this.startUpSearch,
required this.onSuccessDismissPressed,
// required this.startUpSearch,
});
@override
@@ -80,14 +81,17 @@ class _MihDeleteBookmarkAlertState extends State<MihDeleteBookmarkAlert> {
Center(
child: MihButton(
onPressed: () {
context.goNamed(
"mzansiDirectory",
extra: MzansiDirectoryArguments(
personalSearch: false,
startSearchText: widget.business.Name,
packageIndex: 1,
),
);
// context.goNamed(
// "mzansiDirectory",
// extra: MzansiDirectoryArguments(
// personalSearch: false,
// startSearchText: widget.business.Name,
// packageIndex: 1,
// ),
// );
widget.onSuccessDismissPressed!.call();
context.pop();
context.pop();
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),

View File

@@ -0,0 +1,319 @@
import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_employee.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_dropdwn_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_delete_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/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 {
internetConnectionPopUp();
}
}
Future<void> deleteNoteApiCall() 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";
successPopUp(message, false);
} else {
internetConnectionPopUp();
}
}
void showDeleteWarning() {
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => MIHDeleteMessage(
deleteType: "Employee",
onTap: () {
deleteNoteApiCall();
}));
}
void successPopUp(String message, bool stayOnPersonalSide) {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.check_circle_outline_rounded,
size: 150,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Successfully Updated Profile",
alertBody: Column(
children: [
Text(
message,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.pop();
context.pop();
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
elevation: 10,
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
// return MIHSuccessMessage(
// successType: "Success",
// successMessage: message,
// );
},
);
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
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 {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(
errorType: "Input Error");
},
);
}
} else {
MihAlertServices().formNotFilledCompletely(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,
),
),
),
),
],
),
],
),
),
);
},
);
}
}

View File

@@ -3,7 +3,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business_review.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
@@ -13,23 +12,28 @@ import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/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:supertokens_flutter/supertokens.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
@@ -47,9 +51,8 @@ class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
TextEditingController();
late final VoidCallback _reviewDescriptionListener;
final ValueNotifier<int> _counter = ValueNotifier<int>(0);
String userId = "";
void showDeleteReviewAlert() {
void showDeleteReviewAlert(MzansiDirectoryProvider directoryProvider) {
showDialog(
context: context,
builder: (context) => MihPackageAlert(
@@ -93,10 +96,11 @@ class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
widget.businessReview!.rating_score,
widget.business.rating,
)
.then((statusCode) {
.then((statusCode) async {
context.pop(); //Remove loading dialog
context.pop(); //Remove delete dialog
if (statusCode == 200) {
await refreshBusiness(directoryProvider);
context.pop(); //Remove window
successPopUp(
"Successfully Deleted Review!",
@@ -160,7 +164,19 @@ class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
}
}
void submitForm() async {
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) {
@@ -178,9 +194,10 @@ class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
widget.businessReview!.rating_score,
widget.business.rating,
)
.then((statusCode) {
.then((statusCode) async {
context.pop(); //Remove loading dialog
if (statusCode == 200) {
await refreshBusiness(directoryProvider);
context.pop();
successPopUp(
"Successfully Updated Review!",
@@ -197,16 +214,17 @@ class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
} else {
await MihMzansiDirectoryServices()
.addBusinessReview(
userId,
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) {
.then((statusCode) async {
context.pop(); //Remove loading dialog
if (statusCode == 201) {
await refreshBusiness(directoryProvider);
context.pop();
successPopUp(
"Successfully Added Review!",
@@ -250,13 +268,15 @@ class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
Center(
child: MihButton(
onPressed: () {
context.goNamed(
"mzansiDirectory",
extra: MzansiDirectoryArguments(
personalSearch: false,
startSearchText: widget.business.Name,
),
);
// context.goNamed(
// "mzansiDirectory",
// extra: MzansiDirectoryArguments(
// personalSearch: false,
// startSearchText: widget.business.Name,
// ),
// );
widget.onSuccessDismissPressed!.call();
context.pop();
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
@@ -323,265 +343,277 @@ class _MihReviewBusinessWindowState extends State<MihReviewBusinessWindow> {
} else {
_reviewScoreController.text = "1.0"; // Default score
}
SuperTokens.getUserId().then((value) {
setState(() {
userId = value;
});
});
}
@override
Widget build(BuildContext context) {
// return const Placeholder();
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();
},
),
]
: null,
windowBody: MihSingleChildScroll(
child: Padding(
padding:
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
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(
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"),
fontSize: 18,
fontWeight: FontWeight.bold,
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()
.formNotFilledCompletely(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,
),
),
),
),
),
],
),
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();
} else {
MihAlertServices().formNotFilledCompletely(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,
),
),
),
),
),
],
),
],
),
),
),
),
);
},
);
}
}

View File

@@ -0,0 +1,705 @@
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_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/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) {
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.check_circle_outline_rounded,
size: 150,
color: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Successfully Updated Profile",
alertBody: Column(
children: [
Text(
message,
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 25),
Center(
child: MihButton(
onPressed: () {
context.pop();
},
buttonColor: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
elevation: 10,
width: 300,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
alertColour: MihColors.getGreenColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
// return MIHSuccessMessage(
// successType: "Success",
// successMessage: message,
// );
},
);
}
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
showDialog(
context: context,
builder: (context) {
return MihPackageAlert(
alertIcon: Icon(
Icons.warning_rounded,
color: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
),
alertTitle: "Error Updating Business Details",
alertBody: Column(
children: [
Text(
"An error occurred while updating the business details. Please check internet connection and try again.",
style: TextStyle(
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
],
),
alertColour: MihColors.getRedColor(
MzansiInnovationHub.of(context)!.theme.mode == "Dark"),
);
},
);
}
} else {
context.pop();
if (!mounted) return;
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Input Error");
},
);
}
}
@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()
.formNotFilledCompletely(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),
],
),
],
),
),
),
);
},
);
}
}

View File

@@ -1,23 +1,20 @@
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_details.dart';
import 'package:flutter/material.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:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/package_tools/mih_my_business_user.dart';
import 'package:provider/provider.dart';
class MzansiBusinessProfile extends StatefulWidget {
final BusinessArguments arguments;
const MzansiBusinessProfile({
super.key,
required this.arguments,
});
@override
@@ -25,28 +22,6 @@ class MzansiBusinessProfile extends StatefulWidget {
}
class _MzansiBusinessProfileState extends State<MzansiBusinessProfile> {
int _selcetedIndex = 0;
late Future<String> futureLogoUrl;
late Future<String> futureProPicUrl;
late Future<String> futureUserSignatureUrl;
@override
void initState() {
super.initState();
futureLogoUrl = MihFileApi.getMinioFileUrl(
widget.arguments.business!.logo_path,
context,
);
futureProPicUrl = MihFileApi.getMinioFileUrl(
widget.arguments.signedInUser.pro_pic_path,
context,
);
futureUserSignatureUrl = MihFileApi.getMinioFileUrl(
widget.arguments.businessUser!.sig_path,
context,
);
}
@override
Widget build(BuildContext context) {
return MihPackage(
@@ -54,11 +29,9 @@ class _MzansiBusinessProfileState extends State<MzansiBusinessProfile> {
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
selectedbodyIndex: context.watch<MzansiProfileProvider>().businessIndex,
onIndexChange: (newIndex) {
context.read<MzansiProfileProvider>().setBusinessIndex(newIndex);
},
);
}
@@ -70,9 +43,9 @@ class _MzansiBusinessProfileState extends State<MzansiBusinessProfile> {
onTap: () {
context.goNamed(
'mihHome',
extra: false,
);
FocusScope.of(context).unfocus();
context.read<MzansiProfileProvider>().setBusinessIndex(0);
},
);
}
@@ -80,95 +53,43 @@ class _MzansiBusinessProfileState extends State<MzansiBusinessProfile> {
MihPackageTools getTools() {
Map<Widget, void Function()?> temp = {};
temp[const Icon(Icons.business)] = () {
setState(() {
_selcetedIndex = 0;
});
context.read<MzansiProfileProvider>().setBusinessIndex(0);
};
temp[const Icon(Icons.person)] = () {
setState(() {
_selcetedIndex = 1;
});
context.read<MzansiProfileProvider>().setBusinessIndex(1);
};
// temp[const Icon(Icons.warning)] = () {
// setState(() {
// _selcetedIndex = 2;
// });
// };
temp[const Icon(Icons.people)] = () {
setState(() {
_selcetedIndex = 2;
});
context.read<MzansiProfileProvider>().setBusinessIndex(2);
};
temp[const Icon(Icons.add)] = () {
setState(() {
_selcetedIndex = 3;
});
context
.read<MzansiProfileProvider>()
.setUserearchResults(userSearchResults: []);
context.read<MzansiProfileProvider>().setBusinessIndex(3);
};
temp[const Icon(Icons.star_rate_rounded)] = () {
setState(() {
_selcetedIndex = 4;
});
context.read<MzansiProfileProvider>().setBusinessIndex(4);
};
temp[const Icon(Icons.qr_code_rounded)] = () {
setState(() {
_selcetedIndex = 5;
});
context.read<MzansiProfileProvider>().setBusinessIndex(5);
};
return MihPackageTools(
tools: temp,
selcetedIndex: _selcetedIndex,
selcetedIndex: context.watch<MzansiProfileProvider>().businessIndex,
);
}
List<Widget> getToolBody() {
List<Widget> toolBodies = [
FutureBuilder(
future: futureLogoUrl,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: Mihloadingcircle());
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
final logoUrl = snapshot.data!.isNotEmpty
? NetworkImage(snapshot.data!)
: null;
return MihBusinessDetails(
arguments: widget.arguments,
logoImage: logoUrl,
);
} else {
return Text("Error: ${snapshot.error}");
}
}),
FutureBuilder<List<String>>(
future: Future.wait([futureProPicUrl, futureUserSignatureUrl]),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: Mihloadingcircle());
} else if (snapshot.connectionState == ConnectionState.done &&
snapshot.hasData) {
final proPicUrl = NetworkImage(snapshot.data![0]);
print("=============== Signature URL: ${snapshot.data![1]}");
final signatureUrl = snapshot.data![1].isNotEmpty
? NetworkImage(snapshot.data![1])
: null;
return MihMyBusinessUser(
arguments: widget.arguments,
userProPicImage: proPicUrl,
userSignatureImage: signatureUrl,
);
} else {
return Text("Error: ${snapshot.error}");
}
},
),
// MihBusinessProfile(arguments: widget.arguments),
MihMyBusinessTeam(arguments: widget.arguments),
MihBusinessUserSearch(arguments: widget.arguments),
MihBusinessReviews(business: widget.arguments.business!),
MihBusinessDetails(),
MihMyBusinessUser(),
MihMyBusinessTeam(),
MihBusinessUserSearch(),
MihBusinessReviews(
business: context.watch<MzansiProfileProvider>().business!),
MihBusinessQrCode(
business: widget.arguments.business!,
startUpSearch: "",
business: context.watch<MzansiProfileProvider>().business!,
// startUpSearch: "",
),
];
return toolBodies;

View File

@@ -1,23 +1,22 @@
import 'package:go_router/go_router.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_profile_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 BusinessViewArguments? arguments;
final String? businessId;
const MzansiBusinessProfileView({
super.key,
required this.arguments,
required this.businessId,
});
@@ -28,16 +27,10 @@ class MzansiBusinessProfileView extends StatefulWidget {
class _MzansiBusinessProfileViewState extends State<MzansiBusinessProfileView> {
int _selcetedIndex = 0;
Business? business;
String startUpSearch = "";
Future<void> _fetchBusinessDetails() async {
if (widget.arguments != null) {
setState(() {
business = widget.arguments!.business;
startUpSearch = widget.arguments!.startUpSearch ?? "";
});
} else if (widget.businessId != null) {
Future<void> _fetchBusinessDetails(
MzansiDirectoryProvider directoryProvider) async {
if (widget.businessId != null) {
final biz = await MihBusinessDetailsServices()
.getBusinessDetailsByBusinessId(widget.businessId!);
if (biz == null) {
@@ -47,10 +40,7 @@ class _MzansiBusinessProfileViewState extends State<MzansiBusinessProfileView> {
);
} else {
KenLogger.success("Business found: ${biz.Name}");
setState(() {
business = biz;
startUpSearch = "";
});
directoryProvider.setSelectedBusiness(business: biz);
}
}
}
@@ -58,32 +48,39 @@ class _MzansiBusinessProfileViewState extends State<MzansiBusinessProfileView> {
@override
void initState() {
super.initState();
_fetchBusinessDetails();
MzansiDirectoryProvider directoryProvider =
context.read<MzansiDirectoryProvider>();
_fetchBusinessDetails(directoryProvider);
}
@override
Widget build(BuildContext context) {
if (business == null) {
KenLogger.warning("Business is null, showing loading indicator");
return Scaffold(
body: const Center(
child: Mihloadingcircle(),
),
);
} else {
return MihPackage(
appActionButton: getAction(),
appTools: getTools(),
appBody: getToolBody(),
appToolTitles: getToolTitle(),
selectedbodyIndex: _selcetedIndex,
onIndexChange: (newValue) {
setState(() {
_selcetedIndex = newValue;
});
},
);
}
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() {
@@ -91,13 +88,18 @@ class _MzansiBusinessProfileViewState extends State<MzansiBusinessProfileView> {
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
context.goNamed(
"mzansiDirectory",
extra: MzansiDirectoryArguments(
personalSearch: false,
startSearchText: business!.Name,
),
);
MzansiProfileProvider profileProvider =
context.read<MzansiProfileProvider>();
if (profileProvider.user == null) {
context.goNamed(
'mihHome',
);
} else {
context.pop();
}
// context.goNamed(
// "mzansiDirectory",
// );
FocusScope.of(context).unfocus();
},
);
@@ -126,16 +128,12 @@ class _MzansiBusinessProfileViewState extends State<MzansiBusinessProfileView> {
);
}
List<Widget> getToolBody() {
List<Widget> getToolBody(MzansiDirectoryProvider directoryProvider) {
List<Widget> toolBodies = [
MihBusinessDetailsView(
business: business!,
startUpSearch: startUpSearch,
),
MihBusinessReviews(business: business!),
MihBusinessDetailsView(),
MihBusinessReviews(business: directoryProvider.selectedBusiness!),
MihBusinessQrCode(
business: business!,
startUpSearch: startUpSearch,
business: directoryProvider.selectedBusiness!,
)
];
return toolBodies;

View File

@@ -0,0 +1,72 @@
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
import 'package:mzansi_innovation_hub/mih_components/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> {
@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() {
List<Widget> toolBodies = [
MihBusinessDetailsSetUp(),
];
return toolBodies;
}
}

View File

@@ -2,16 +2,13 @@ import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
class MzansiBusinessProfileTile extends StatefulWidget {
final BusinessArguments arguments;
final double packageSize;
const MzansiBusinessProfileTile({
super.key,
required this.arguments,
required this.packageSize,
});
@@ -27,7 +24,6 @@ class _MzansiBusinessProfileTileState extends State<MzansiBusinessProfileTile> {
onTap: () {
context.goNamed(
"businessProfileManage",
extra: widget.arguments,
);
// Navigator.of(context).pushNamed(
// '/business-profile/manage',

View File

@@ -2,16 +2,15 @@ import 'package:go_router/go_router.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tile.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:flutter/material.dart';
import 'package:mzansi_innovation_hub/mih_components/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 AppUser signedInUser;
final double packageSize;
const MzansiSetupBusinessProfileTile({
super.key,
required this.signedInUser,
required this.packageSize,
});
@@ -24,11 +23,13 @@ class _MzansiSetupBusinessProfileTileState
extends State<MzansiSetupBusinessProfileTile> {
@override
Widget build(BuildContext context) {
MzansiProfileProvider profileProvider =
context.read<MzansiProfileProvider>();
return MihPackageTile(
onTap: () {
context.goNamed(
'businessProfileSetup',
extra: widget.signedInUser,
extra: profileProvider.user,
);
// Navigator.of(context).pushNamed(
// '/business-profile/set-up',

View File

@@ -1,53 +1,43 @@
import 'dart:convert';
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_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_image_display.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
import 'package:mzansi_innovation_hub/mih_components/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:mzansi_innovation_hub/mih_components/mih_layout/mih_action.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_header.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_layout/mih_layout_builder.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_form.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_text_form_field.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_error_message.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:file_picker/file_picker.dart';
import 'package:provider/provider.dart';
class ProfileBusinessAdd extends StatefulWidget {
//final BusinessUserScreenArguments arguments;
final AppUser signedInUser;
const ProfileBusinessAdd({
super.key,
required this.signedInUser,
});
class MihBusinessDetailsSetUp extends StatefulWidget {
const MihBusinessDetailsSetUp({super.key});
@override
State<ProfileBusinessAdd> createState() => _ProfileBusinessAddState();
State<MihBusinessDetailsSetUp> createState() =>
_MihBusinessDetailsSetUpState();
}
class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
final FocusNode _focusNode = FocusNode();
final baseAPI = AppEnviroment.baseApiUrl;
class _MihBusinessDetailsSetUpState extends State<MihBusinessDetailsSetUp> {
final nameController = TextEditingController();
final typeController = TextEditingController();
final regController = TextEditingController();
final addressController = TextEditingController();
final logonameController = TextEditingController();
final fnameController = TextEditingController();
final lnameController = TextEditingController();
final titleController = TextEditingController();
@@ -62,65 +52,33 @@ class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
final websiteController = TextEditingController();
final ratingController = TextEditingController();
final missionVisionController = TextEditingController();
ImageProvider<Object>? logoPreview;
ImageProvider<Object>? signaturePreview;
PlatformFile? selectedLogo;
PlatformFile? selectedSignature;
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("");
final _formKey = GlobalKey<FormState>();
late String env;
Future<bool> uploadFile(String id, PlatformFile? selectedFile) async {
print("Inside uploud file method");
int uploadStatusCode = 0;
uploadStatusCode = await MihFileApi.uploadFile(
id,
env,
"business_files",
selectedFile,
context,
);
print("Status code: $uploadStatusCode");
if (uploadStatusCode == 200) {
return true;
void submitForm(MzansiProfileProvider mzansiProfileProvider) {
if (isFieldsFilled()) {
createBusinessProfileAPICall(mzansiProfileProvider);
} else {
return false;
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Input Error");
},
);
}
}
Future<void> createBusinessUserAPICall(String business_id) async {
print("Inside create bus user method");
int statusCode = await MihMyBusinessUserServices().createBusinessUser(
business_id,
widget.signedInUser.app_id,
signtureController.text,
titleController.text,
accessController.text,
context,
);
print("Status code: $statusCode");
if (statusCode == 201) {
// Navigator.of(context).pop();
// Navigator.of(context).popAndPushNamed(
// '/',
// arguments: AuthArguments(false, false),
// );
String message =
"Your business profile is now live! You can now start connecting with customers and growing your business.";
successPopUp(message, false);
} else {
internetConnectionPopUp();
}
}
Future<void> createBusinessProfileAPICall() async {
print("Inside create business profile method");
Future<void> createBusinessProfileAPICall(
MzansiProfileProvider mzansiProfileProvider) async {
Response response =
await MihBusinessDetailsServices().createBusinessDetails(
widget.signedInUser.app_id,
mzansiProfileProvider,
nameController.text,
typeController.text,
regController.text,
@@ -128,23 +86,87 @@ class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
vatNoController.text,
emailController.text,
getNumberWithCountryCode(),
// "${countryCodeController.text}-${contactController.text}",
locationController.text,
logonameController.text,
logoFileNameController.text,
websiteController.text,
"0",
missionVisionController.text,
context,
);
print(response.body);
if (response.statusCode == 201) {
var businessResponse = jsonDecode(response.body);
createBusinessUserAPICall(businessResponse['business_id']);
bool successUpload =
await uploadFile(mzansiProfileProvider, newSelectedLogoPic);
if (successUpload) {
String logoUrl = await MihFileApi.getMinioFileUrl(
mzansiProfileProvider.business!.logo_path, context);
mzansiProfileProvider.setBusinessProfilePicUrl(logoUrl);
}
await createBusinessUserAPICall(mzansiProfileProvider);
} else {
internetConnectionPopUp();
}
}
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, context);
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 {
internetConnectionPopUp();
}
} else {
internetConnectionPopUp();
}
}
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") {
@@ -157,13 +179,22 @@ class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
return "${countryCodeController.text}-$numberWithoutBeginingZero";
}
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
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) {
@@ -227,110 +258,90 @@ class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
);
}
bool isFieldsFilled() {
if (typeController.text.isEmpty ||
titleController.text.isEmpty ||
accessController.text.isEmpty) {
return false;
} else {
return true;
}
}
void submitForm() {
if (isFieldsFilled()) {
print("Inside submit method");
createBusinessProfileAPICall();
} else {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Input Error");
},
);
}
}
void emailError() {
void internetConnectionPopUp() {
showDialog(
context: context,
builder: (context) {
return const MIHErrorMessage(errorType: "Invalid Email");
return const MIHErrorMessage(errorType: "Internet Connection");
},
);
}
bool isEmailValid() {
String text = emailController.text;
var regex = RegExp(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$');
return regex.hasMatch(text);
}
// bool validEmail() {
// String text = emailController.text;
// var regex = RegExp(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$');
// return regex.hasMatch(text);
// }
void typeSelected() {
if (typeController.text.isNotEmpty) {
busType.value = typeController.text;
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 {
busType.value = "";
env = "Dev";
}
missionVisionController.addListener(() {
setState(() {
_counter.value = missionVisionController.text.characters.length;
});
});
}
MIHAction getActionButton() {
return MIHAction(
icon: const Icon(Icons.arrow_back),
iconSize: 35,
onTap: () {
// Navigator.of(context).pop();
context.goNamed(
'mihHome',
extra: true,
);
},
);
@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();
}
MIHHeader getHeader() {
return const MIHHeader(
headerAlignment: MainAxisAlignment.center,
headerItems: [
Text(
"Set Up Business Profile",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
),
),
],
);
@override
void initState() {
super.initState();
initialiseControlers(context.read<MzansiProfileProvider>());
}
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");
}
}
MIHBody getBody(double width) {
return MIHBody(
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MihPackageToolBody(
borderOn: false,
bodyItems: [
KeyboardListener(
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();
submitForm(mzansiProfileProvider);
} else {
MihAlertServices().formNotFilledCompletely(context);
}
@@ -345,7 +356,7 @@ class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
child: Column(
children: [
const Text(
"My Business Details",
"Business Details",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 25,
@@ -359,6 +370,29 @@ class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
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 ==
@@ -387,7 +421,8 @@ class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
requiredText: true,
hintText: "Business Type",
validator: (value) {
return MihValidationServices().isEmpty(value);
return MihValidationServices()
.validateNoSpecialChars(value);
},
),
const SizedBox(height: 10.0),
@@ -643,7 +678,7 @@ class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
//const SizedBox(height: 15.0),
const Center(
child: Text(
"My Business User",
"Business User",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22,
@@ -715,7 +750,7 @@ class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
return MihValidationServices().isEmpty(value);
},
),
const SizedBox(height: 15.0),
const SizedBox(height: 10.0),
MihTextFormField(
fillColor: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
@@ -732,23 +767,41 @@ class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
return MihValidationServices().isEmpty(value);
},
),
// MihDropdownField(
// controller: accessController,
// hintText: "Access Type",
// dropdownOptions: const ["Full", "Partial"],
// editable: false,
// enableSearch: true,
// validator: (value) {
// return MihValidationServices().isEmpty(value);
// },
// requiredText: true,
// ),
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();
submitForm(mzansiProfileProvider);
} else {
MihAlertServices()
.formNotFilledCompletely(context);
@@ -770,72 +823,15 @@ class _ProfileBusinessAddState extends State<ProfileBusinessAdd> {
),
),
),
const SizedBox(height: 30),
],
),
],
),
),
),
),
],
);
}
@override
void dispose() {
nameController.dispose();
typeController.dispose();
regController.dispose();
logonameController.dispose();
fnameController.dispose();
lnameController.dispose();
titleController.dispose();
signtureController.dispose();
accessController.dispose();
contactController.dispose();
emailController.dispose();
locationController.dispose();
practiceNoController.dispose();
vatNoController.dispose();
_focusNode.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
typeController.addListener(typeSelected);
setState(() {
fnameController.text = widget.signedInUser.fname;
lnameController.text = widget.signedInUser.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
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
return MIHLayoutBuilder(
actionButton: getActionButton(),
secondaryActionButton: null,
header: getHeader(),
body: getBody(screenWidth),
actionDrawer: null,
secondaryActionDrawer: null,
bottomNavBar: null,
pullDownToRefresh: false,
onPullDown: () async {},
);
},
);
}
}

View File

@@ -2,22 +2,19 @@ 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_components/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_profile/business_profile/components/mih_business_info_card.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_single_child_scroll.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
import 'package:provider/provider.dart';
class MihBusinessDetailsView extends StatefulWidget {
final Business business;
final String? startUpSearch;
const MihBusinessDetailsView({
super.key,
required this.business,
required this.startUpSearch,
});
@override
@@ -36,8 +33,10 @@ class _MihBusinessDetailsViewState extends State<MihBusinessDetailsView> {
@override
void initState() {
super.initState();
futureImageUrl =
MihFileApi.getMinioFileUrl(widget.business.logo_path, context);
MzansiDirectoryProvider directoryProvider =
context.read<MzansiDirectoryProvider>();
futureImageUrl = MihFileApi.getMinioFileUrl(
directoryProvider.selectedBusiness!.logo_path, context);
}
@override
@@ -52,173 +51,182 @@ class _MihBusinessDetailsViewState extends State<MihBusinessDetailsView> {
Widget getBody(double width, BuildContext context) {
double profilePictureWidth = 150;
return Stack(
children: [
MihSingleChildScroll(
child: Padding(
padding:
MzansiInnovationHub.of(context)!.theme.screenType == "desktop"
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: NetworkImage(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,
child: Column(
children: [
FutureBuilder(
future: futureImageUrl,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState ==
ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "") {
return MihCircleAvatar(
imageFile:
NetworkImage(asyncSnapshot.requireData),
width: profilePictureWidth,
editable: false,
fileNameController: TextEditingController(),
userSelectedfile: file,
frameColor: 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"),
);
}
}),
// 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(
widget.business.Name,
style: TextStyle(
fontSize: 35,
fontWeight: FontWeight.bold,
color: MihColors.getSecondaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
),
),
),
FittedBox(
child: Text(
widget.business.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(
widget.business.mission_vision.isNotEmpty
? widget.business.mission_vision
: "No Mission & Vision added yet",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: 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,
),
),
],
),
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: widget.business.rating.isNotEmpty
? double.parse(widget.business.rating)
: 0,
maxRating: 5,
),
const SizedBox(height: 20),
SizedBox(
width: 700,
child: MihBusinessCard(
business: widget.business,
startUpSearch: widget.startUpSearch,
// businessid: widget.business.business_id,
// businessName: widget.business.Name,
// cellNumber: widget.business.contact_no,
// email: widget.business.bus_email,
// gpsLocation: widget.business.gps_location,
// rating: widget.business.rating.isNotEmpty
// ? double.parse(widget.business.rating)
// : 0,
// website: widget.business.website,
width: width,
),
),
],
),
),
),
),
],
],
);
},
);
}
}

View File

@@ -1,4 +1,3 @@
import 'dart:typed_data';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:file_picker/file_picker.dart';
import 'package:file_saver/file_saver.dart';
@@ -21,15 +20,16 @@ import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tool_body.dart';
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
import 'package:screenshot/screenshot.dart';
import 'package:share_plus/share_plus.dart';
import 'package:supertokens_flutter/supertokens.dart';
class MihBusinessQrCode extends StatefulWidget {
final Business business;
final String? startUpSearch;
// final String? startUpSearch;
const MihBusinessQrCode({
super.key,
required this.business,
required this.startUpSearch,
// required this.startUpSearch,
});
@override
@@ -89,43 +89,6 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
mimeType: MimeType.png,
);
}
// if (kIsWeb) {
// final blob = html.Blob([imageBytes]);
// final url = html.Url.createObjectUrlFromBlob(blob);
// final anchor = html.document.createElement('a') as html.AnchorElement
// ..href = url
// ..style.display = 'none'
// ..download = filename; // Suggested filename for the download
// html.document.body!.children.add(anchor);
// anchor.click(); // Programmatically click the link to trigger download
// html.document.body!.children.remove(anchor);
// html.Url.revokeObjectUrl(url);
// } else {
// var permission = await FlDownloader.requestPermission();
// if (permission == StoragePermissionStatus.granted) {
// try {
// mihLoadingPopUp();
// KenLogger.success("Downloading from URL: $url");
// await FlDownloader.download(url);
// Navigator.of(context).pop();
// } on Exception catch (error) {
// Navigator.of(context).pop();
// print(error);
// }
// } else {
// print("denied");
// }
// try {
// final directory = await getDownloadsDirectory();
// final file = File('${directory?.path}/$filename');
// await file.writeAsBytes(imageBytes);
// KenLogger.success("File saved at: ${file.path}");
// } catch (e) {
// KenLogger.error("Error saving file: $e");
// }
// }
}
void mihLoadingPopUp() {
@@ -139,10 +102,6 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
Future<void> downloadQrCode() async {
if (_isUserSignedIn) {
// final Uri uri = Uri.parse(getQrCodeData(1024));
// if (!await launchUrl(uri)) {
// throw 'Could not launch $uri';
// }
await screenshotController.capture().then((image) {
KenLogger.success("Image Captured: $image");
setState(() {
@@ -244,7 +203,8 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
if (asyncSnapshot.connectionState ==
ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "") {
if (asyncSnapshot.requireData != "" ||
asyncSnapshot.requireData.isNotEmpty) {
return MihCircleAvatar(
imageFile: NetworkImage(asyncSnapshot.requireData),
width: profilePictureWidth,
@@ -263,7 +223,7 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
return Icon(
MihIcons.iDontKnow,
size: profilePictureWidth,
color: MihColors.getSecondaryColor(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
);
@@ -272,7 +232,7 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
return Icon(
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.getSecondaryColor(
color: MihColors.getPrimaryColor(
MzansiInnovationHub.of(context)!.theme.mode ==
"Dark"),
);
@@ -360,6 +320,13 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
);
}
void shareMIHLink(BuildContext context, String message, String link) {
String shareText = "$message: $link";
SharePlus.instance.share(
ShareParams(text: shareText),
);
}
@override
void dispose() {
super.dispose();
@@ -431,7 +398,31 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
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 ${widget.business.Name} on the MIH app",
"$qrCodedata${widget.business.business_id}",
);
},
),
]),
)
],

View File

@@ -41,6 +41,7 @@ class _MihBusinessReviewsState extends State<MihBusinessReviews> {
businessReview: businessReview,
screenWidth: width,
readOnly: true,
onSuccessDismissPressed: () {},
);
},
);

Some files were not shown because too many files have changed in this diff Show More