diff --git a/mih_ui/lib/main_dev.dart b/mih_ui/lib/main_dev.dart index fd7a07c0..645315c3 100644 --- a/mih_ui/lib/main_dev.dart +++ b/mih_ui/lib/main_dev.dart @@ -12,6 +12,7 @@ import 'package:mzansi_innovation_hub/mih_config/mih_go_router.dart'; import 'package:mzansi_innovation_hub/mih_hive/hive_registrar.g.dart'; import 'package:mzansi_innovation_hub/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_objects/business_employee.dart'; import 'package:mzansi_innovation_hub/mih_objects/business_user.dart'; import 'package:mzansi_innovation_hub/mih_objects/profile_link.dart'; import 'package:mzansi_innovation_hub/mih_objects/user_consent.dart'; @@ -36,6 +37,8 @@ void main() async { await Hive.openBox('user_consent_box'); await Hive.openBox('image_urls_box'); await Hive.openBox('personal_profile_links_box'); + await Hive.openBox('business_profile_links_box'); + await Hive.openBox('business_employees_box'); // await Firebase.initializeApp( // // options: DefaultFirebaseOptions.currentPlatform, diff --git a/mih_ui/lib/mih_config/mih_go_router.dart b/mih_ui/lib/mih_config/mih_go_router.dart index 36b7a22f..d1756d98 100644 --- a/mih_ui/lib/mih_config/mih_go_router.dart +++ b/mih_ui/lib/mih_config/mih_go_router.dart @@ -171,9 +171,7 @@ class MihGoRouter { path: MihGoRouterPaths.mihHome, builder: (BuildContext context, GoRouterState state) { KenLogger.success("MihGoRouter: mihHome"); - return MihHome( - key: UniqueKey(), - ); + return MihHome(); }, routes: [ // ========================== About MIH ================================== diff --git a/mih_ui/lib/mih_hive/hive_adapters.dart b/mih_ui/lib/mih_hive/hive_adapters.dart index 5fc537d3..40db3c0e 100644 --- a/mih_ui/lib/mih_hive/hive_adapters.dart +++ b/mih_ui/lib/mih_hive/hive_adapters.dart @@ -2,6 +2,7 @@ import 'package:hive_ce/hive_ce.dart'; import 'package:mzansi_innovation_hub/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_objects/business_employee.dart'; import 'package:mzansi_innovation_hub/mih_objects/business_user.dart'; import 'package:mzansi_innovation_hub/mih_objects/profile_link.dart'; import 'package:mzansi_innovation_hub/mih_objects/user_consent.dart'; @@ -12,5 +13,6 @@ import 'package:mzansi_innovation_hub/mih_objects/user_consent.dart'; AdapterSpec(), AdapterSpec(), AdapterSpec(), + AdapterSpec(), ]) part 'hive_adapters.g.dart'; diff --git a/mih_ui/lib/mih_hive/hive_adapters.g.dart b/mih_ui/lib/mih_hive/hive_adapters.g.dart index 2b2abeac..0431eab4 100644 --- a/mih_ui/lib/mih_hive/hive_adapters.g.dart +++ b/mih_ui/lib/mih_hive/hive_adapters.g.dart @@ -283,3 +283,58 @@ class ProfileLinkAdapter extends TypeAdapter { runtimeType == other.runtimeType && typeId == other.typeId; } + +class BusinessEmployeeAdapter extends TypeAdapter { + @override + final typeId = 5; + + @override + BusinessEmployee read(BinaryReader reader) { + final numOfFields = reader.readByte(); + final fields = { + for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), + }; + return BusinessEmployee( + fields[0] as String, + fields[1] as String, + fields[2] as String, + fields[3] as String, + fields[4] as String, + fields[5] as String, + fields[6] as String, + fields[7] as String, + ); + } + + @override + void write(BinaryWriter writer, BusinessEmployee obj) { + writer + ..writeByte(8) + ..writeByte(0) + ..write(obj.business_id) + ..writeByte(1) + ..write(obj.app_id) + ..writeByte(2) + ..write(obj.title) + ..writeByte(3) + ..write(obj.access) + ..writeByte(4) + ..write(obj.fname) + ..writeByte(5) + ..write(obj.lname) + ..writeByte(6) + ..write(obj.email) + ..writeByte(7) + ..write(obj.username); + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is BusinessEmployeeAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} diff --git a/mih_ui/lib/mih_hive/hive_adapters.g.yaml b/mih_ui/lib/mih_hive/hive_adapters.g.yaml index 1dbf08fc..c8fb856c 100644 --- a/mih_ui/lib/mih_hive/hive_adapters.g.yaml +++ b/mih_ui/lib/mih_hive/hive_adapters.g.yaml @@ -1,7 +1,7 @@ # Generated by Hive CE # Manual modifications may be necessary for certain migrations # Check in to version control -nextTypeId: 5 +nextTypeId: 6 types: AppUser: typeId: 0 @@ -105,3 +105,23 @@ types: index: 5 order: index: 6 + BusinessEmployee: + typeId: 5 + nextIndex: 8 + fields: + business_id: + index: 0 + app_id: + index: 1 + title: + index: 2 + access: + index: 3 + fname: + index: 4 + lname: + index: 5 + email: + index: 6 + username: + index: 7 diff --git a/mih_ui/lib/mih_hive/hive_registrar.g.dart b/mih_ui/lib/mih_hive/hive_registrar.g.dart index 46afbf71..641002d4 100644 --- a/mih_ui/lib/mih_hive/hive_registrar.g.dart +++ b/mih_ui/lib/mih_hive/hive_registrar.g.dart @@ -9,6 +9,7 @@ extension HiveRegistrar on HiveInterface { void registerAdapters() { registerAdapter(AppUserAdapter()); registerAdapter(BusinessAdapter()); + registerAdapter(BusinessEmployeeAdapter()); registerAdapter(BusinessUserAdapter()); registerAdapter(ProfileLinkAdapter()); registerAdapter(UserConsentAdapter()); @@ -19,6 +20,7 @@ extension IsolatedHiveRegistrar on IsolatedHiveInterface { void registerAdapters() { registerAdapter(AppUserAdapter()); registerAdapter(BusinessAdapter()); + registerAdapter(BusinessEmployeeAdapter()); registerAdapter(BusinessUserAdapter()); registerAdapter(ProfileLinkAdapter()); registerAdapter(UserConsentAdapter()); diff --git a/mih_ui/lib/mih_hive/mzansi_profile_hive_data.dart b/mih_ui/lib/mih_hive/mzansi_profile_hive_data.dart index 51439e8c..cd818fff 100644 --- a/mih_ui/lib/mih_hive/mzansi_profile_hive_data.dart +++ b/mih_ui/lib/mih_hive/mzansi_profile_hive_data.dart @@ -2,10 +2,12 @@ import 'package:hive_ce_flutter/hive_ce_flutter.dart'; import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_objects/business.dart'; +import 'package:mzansi_innovation_hub/mih_objects/business_employee.dart'; import 'package:mzansi_innovation_hub/mih_objects/business_user.dart'; import 'package:mzansi_innovation_hub/mih_objects/profile_link.dart'; import 'package:mzansi_innovation_hub/mih_objects/user_consent.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; +import 'package:mzansi_innovation_hub/mih_services/mih_business_employee_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_profile_links_service.dart'; @@ -21,7 +23,10 @@ class MzansiProfileHiveData { Hive.box('user_consent_box'); final Box _personalProfileLinksBox = Hive.box('personal_profile_links_box'); - + final Box _businessProfileLinksBox = + Hive.box('business_profile_links_box'); + final Box _businessEmployeesBox = + Hive.box('business_Employees_box'); final Box _resolvedUrlsBox = Hive.box('image_urls_box'); static const String kUserKey = 'current_user'; @@ -32,6 +37,7 @@ class MzansiProfileHiveData { static const String kBusinessPicUrlKey = 'business_pic_url'; static const String kSignatureUrlKey = 'signature_url'; + // Get Data from local storage AppUser? getCachedUser() => _userBox.get(kUserKey); Business? getCachedBusiness() => _businessBox.get(kBusinessKey); BusinessUser? getCachedBusinessUser() => @@ -40,12 +46,26 @@ class MzansiProfileHiveData { String? getCachedUserPicUrl() => _resolvedUrlsBox.get(kUserPicUrlKey); String? getCachedBusinessPicUrl() => _resolvedUrlsBox.get(kBusinessPicUrlKey); String? getCachedSignatureUrl() => _resolvedUrlsBox.get(kSignatureUrlKey); + List getCachedPersonalProfileLinks() { final links = _personalProfileLinksBox.values.toList(); links.sort((a, b) => a.order.compareTo(b.order)); return links; } + List getCachedBusinessProfileLinks() { + final links = _businessProfileLinksBox.values.toList(); + links.sort((a, b) => a.order.compareTo(b.order)); + return links; + } + + List getCachedBusinessEmployees() { + final employees = _businessEmployeesBox.values.toList(); + employees.sort((a, b) => a.fname.compareTo(b.fname)); + return employees; + } + + // Caching Data to local storage Future cacheUserData(AppUser remoteUser) async { await _userBox.put(kUserKey, remoteUser); if (remoteUser.pro_pic_path.isNotEmpty) { @@ -53,10 +73,12 @@ class MzansiProfileHiveData { await MihFileApi.getMinioFileUrl(remoteUser.pro_pic_path); await _resolvedUrlsBox.put(kUserPicUrlKey, userPicUrl); } + KenLogger.success("User Profile Cached"); } Future cacheUserConsentData(UserConsent remoteConsent) async { await _userConsentBox.put(kConsentKey, remoteConsent); + KenLogger.success("User Consent Cached"); } Future cacheBusinessData(Business remoteBusiness) async { @@ -71,6 +93,7 @@ class MzansiProfileHiveData { if (remoteBizUser != null) { cacheBusinessUserData(remoteBizUser); } + KenLogger.success("Busines Profile Cached"); } Future cacheBusinessUserData(BusinessUser remoteBizUser) async { @@ -80,36 +103,64 @@ class MzansiProfileHiveData { await MihFileApi.getMinioFileUrl(remoteBizUser.sig_path); await _resolvedUrlsBox.put(kSignatureUrlKey, signatureUrl); } + KenLogger.success("Busines User Profile Cached"); + } + + Future cacheBusinessEmployeesData( + List remoteBusinessEmployeeList) async { + await _businessEmployeesBox.clear(); + await _businessEmployeesBox.addAll(remoteBusinessEmployeeList); + KenLogger.success("Business Employees Cached"); } Future cachePersonalProfileLinksData( - List remoteLinks) async { + List remotePersonalLinks) async { await _personalProfileLinksBox.clear(); - await _personalProfileLinksBox.addAll(remoteLinks); + await _personalProfileLinksBox.addAll(remotePersonalLinks); + KenLogger.success("Personal Profile Links Cached"); } - Future syncProfileDataWithServer() async { + Future cacheBusinessProfileLinksData( + List remoteBusinessLinks) async { + await _businessProfileLinksBox.clear(); + await _businessProfileLinksBox.addAll(remoteBusinessLinks); + KenLogger.success("Personal Profile Links Cached"); + } + + // Sync Local Data from data from MIH Server + Future syncProfileDataWithServer() async { try { AppUser? remoteUser = await MihUserServices().getMyUserDetailsV2(); if (remoteUser != null) { cacheUserData(remoteUser); - UserConsent? remoteConsent = await MihUserConsentServices().getUserConsentStatusV2(); if (remoteConsent != null) { cacheUserConsentData(remoteConsent); } - final remoteLinks = await MihProfileLinksServices.getUserProfileLinksV2( - remoteUser.app_id); - await cachePersonalProfileLinksData(remoteLinks); + final remotePersonalLinks = + await MihProfileLinksServices.getUserProfileLinksV2( + remoteUser.app_id); + cachePersonalProfileLinksData(remotePersonalLinks); } Business? remoteBusiness = await MihBusinessDetailsServices().getBusinessDetailsByUserV2(); if (remoteBusiness != null) { cacheBusinessData(remoteBusiness); + + final remoteBusinessEmployeeList = await MihBusinessEmployeeServices() + .fetchEmployeesV2(remoteBusiness.business_id); + cacheBusinessEmployeesData(remoteBusinessEmployeeList); + + final remoteBusinessLinks = + await MihProfileLinksServices.getBusinessProfileLinksV2( + remoteBusiness.business_id); + cacheBusinessProfileLinksData(remoteBusinessLinks); } + return true; } catch (error) { - KenLogger.warning("App operating offline mode. Sync paused"); + KenLogger.warning("App Operating in Offline Mode. Sync Paused"); + return false; // KenLogger.warning("App operating offline mode. Sync paused: $error"); } } diff --git a/mih_ui/lib/mih_packages/mih_home/mih_home.dart b/mih_ui/lib/mih_packages/mih_home/mih_home.dart index dc81c343..cd29c124 100644 --- a/mih_ui/lib/mih_packages/mih_home/mih_home.dart +++ b/mih_ui/lib/mih_packages/mih_home/mih_home.dart @@ -42,9 +42,11 @@ class _MihHomeState extends State { context.read(); mzansiProfileProvider.loadCachedProfileState(); if (mzansiProfileProvider.user == null) { - await mzansiProfileProvider.syncWithCloudPipeline(); + await mzansiProfileProvider.syncWithMihServerData(); + } else { + mzansiProfileProvider.syncWithMihServerData(); } - } + } @override void dispose() { @@ -74,18 +76,32 @@ class _MihHomeState extends State { return Consumer( builder: (BuildContext context, MzansiProfileProvider mzansiProfileProvider, Widget? child) { - if (mzansiProfileProvider.user == null) { - return Scaffold( - body: Center( - child: Mihloadingcircle(), - ), - ); - } + if (mzansiProfileProvider.user == null) { + return Scaffold( + body: Center( + child: Mihloadingcircle(), + ), + ); + } return Stack( children: [ RefreshIndicator( + key: mzansiProfileProvider.refreshIndicatorKey, onRefresh: () async { - await mzansiProfileProvider.syncWithCloudPipeline(); + bool success = + await mzansiProfileProvider.syncWithMihServerData(); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + MihSnackBar( + child: Text( + success + ? "Data Synced with MIH Server." + : "MIH App operation in Offline Mode", + ), + // backgroundColor: success ? null : MihColors.red(), + ), + ); + } }, child: SingleChildScrollView( physics: const AlwaysScrollableScrollPhysics(), diff --git a/mih_ui/lib/mih_packages/mih_home/package_tile/mih_home_refresh_tile.dart b/mih_ui/lib/mih_packages/mih_home/package_tile/mih_home_refresh_tile.dart new file mode 100644 index 00000000..8e7c7d1b --- /dev/null +++ b/mih_ui/lib/mih_packages/mih_home/package_tile/mih_home_refresh_tile.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:mih_package_toolkit/mih_package_toolkit.dart'; +import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart'; +import 'package:provider/provider.dart'; + +class MihHomeRefreshTile extends StatefulWidget { + final double packageSize; + const MihHomeRefreshTile({ + super.key, + required this.packageSize, + }); + + @override + State createState() => _MihHomeRefreshTileState(); +} + +class _MihHomeRefreshTileState extends State { + @override + Widget build(BuildContext context) { + return Consumer( + builder: (BuildContext context, MzansiProfileProvider profileProvider, + Widget? child) { + return MihPackageTile( + onTap: profileProvider.triggerRefresh, + packageName: "Sync Data", + packageIcon: Stack( + alignment: Alignment.center, + children: [ + Icon( + MihIcons.mihRing, + color: MihColors.secondary(), + ), + Center( + child: Transform.scale( + scale: 0.75, + origin: Offset(-4, 0), + child: Icon( + Icons.cloud_sync_rounded, + color: MihColors.secondary(), + ), + ), + ), + ], + ), + iconSize: widget.packageSize, + textColor: MihColors.secondary(), + ); + }, + ); + } +} diff --git a/mih_ui/lib/mih_packages/mih_home/package_tools/mih_business_home.dart b/mih_ui/lib/mih_packages/mih_home/package_tools/mih_business_home.dart index 2e8dda43..ffb82b93 100644 --- a/mih_ui/lib/mih_packages/mih_home/package_tools/mih_business_home.dart +++ b/mih_ui/lib/mih_packages/mih_home/package_tools/mih_business_home.dart @@ -2,6 +2,7 @@ import 'package:go_router/go_router.dart'; import 'package:mih_package_toolkit/mih_package_toolkit.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_objects/arguments.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mih_home/package_tile/mih_home_refresh_tile.dart'; import 'package:mzansi_innovation_hub/mih_providers/mzansi_ai_provider.dart'; import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tile/about_mih_tile.dart'; @@ -129,6 +130,12 @@ class _MihBusinessHomeState extends State packageSize: packageSize, ) }); + //=============== About MIH =============== + temp.add({ + "Sync Data": MihHomeRefreshTile( + packageSize: packageSize, + ) + }); return temp; } diff --git a/mih_ui/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart b/mih_ui/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart index f1ed0494..a2c989a1 100644 --- a/mih_ui/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart +++ b/mih_ui/lib/mih_packages/mih_home/package_tools/mih_personal_home.dart @@ -3,6 +3,7 @@ import 'package:mih_package_toolkit/mih_package_toolkit.dart'; import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:mzansi_innovation_hub/mih_package_components/Example/package_tiles/test_package_tile.dart'; +import 'package:mzansi_innovation_hub/mih_packages/mih_home/package_tile/mih_home_refresh_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_providers/mzansi_ai_provider.dart'; import 'package:mzansi_innovation_hub/mih_packages/about_mih/package_tile/about_mih_tile.dart'; @@ -138,6 +139,12 @@ class _MihPersonalHomeState extends State packageSize: packageSize, ) }); + //=============== About MIH =============== + temp.add({ + "Sync Data": MihHomeRefreshTile( + packageSize: packageSize, + ) + }); //=============== Dev =============== if (AppEnviroment.getEnv() == "Dev") { temp.add({ diff --git a/mih_ui/lib/mih_packages/mzansi_profile/business_profile/busines_profile.dart b/mih_ui/lib/mih_packages/mzansi_profile/business_profile/busines_profile.dart index c13e079c..556f7a55 100644 --- a/mih_ui/lib/mih_packages/mzansi_profile/business_profile/busines_profile.dart +++ b/mih_ui/lib/mih_packages/mzansi_profile/business_profile/busines_profile.dart @@ -22,7 +22,7 @@ class BusinesProfile extends StatefulWidget { } class _BusinesProfileState extends State { - bool _isLoadingInitialData = true; + // bool _isLoadingInitialData = true; late final MihBusinessDetails _businessDetails; late final MihMyBusinessUser _businessUser; late final MihMyBusinessTeam _businessTeam; @@ -31,26 +31,18 @@ class _BusinesProfileState extends State { late final MihBusinessQrCode _businessQrCode; late final MihBusinessLinks _businessLinks; - Future _loadInitialData() async { - setState(() { - _isLoadingInitialData = true; - }); - MzansiProfileProvider mzansiProfileProvider = - context.read(); - if (mzansiProfileProvider.user == null) { - await MihDataHelperServices().loadUserDataWithBusinessesData( - mzansiProfileProvider, - ); - } - await MihProfileLinksServices.getBusinessProfileLinks( - mzansiProfileProvider, mzansiProfileProvider.business!.business_id); - await MihBusinessEmployeeServices() - .fetchEmployees(mzansiProfileProvider, context); - setState(() { - _isLoadingInitialData = false; - }); - } - + // Future _loadInitialData() async { + // MzansiProfileProvider mzansiProfileProvider = + // context.read(); + // mzansiProfileProvider.loadCachedProfileState(); + // if (mzansiProfileProvider.user == null) { + // mzansiProfileProvider.syncWithMihServerData(); + // } + // setState(() { + // _isLoadingInitialData = false; + // }); + // } + // @override void initState() { super.initState(); @@ -61,7 +53,7 @@ class _BusinesProfileState extends State { _businessReviews = MihBusinessReviews(business: null); _businessLinks = MihBusinessLinks(viewMode: false); _businessQrCode = MihBusinessQrCode(business: null); - _loadInitialData(); + // _loadInitialData(); } @override @@ -69,13 +61,13 @@ class _BusinesProfileState extends State { return Consumer( builder: (BuildContext context, MzansiProfileProvider mzansiProfileProvider, Widget? child) { - if (_isLoadingInitialData) { - return Scaffold( - body: Center( - child: Mihloadingcircle(), - ), - ); - } + // if (_isLoadingInitialData) { + // return Scaffold( + // body: Center( + // child: Mihloadingcircle(), + // ), + // ); + // } return MihPackage( packageActionButton: getAction(), packageTools: getTools(), diff --git a/mih_ui/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart b/mih_ui/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart index f03873a4..f2939170 100644 --- a/mih_ui/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart +++ b/mih_ui/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_qr_code.dart @@ -175,6 +175,8 @@ class _MihBusinessQrCodeState extends State { } Widget displayBusinessQRCode(double profilePictureWidth) { + MzansiProfileProvider profileprovider = + context.read(); return Screenshot( controller: screenshotController, child: Material( @@ -193,42 +195,54 @@ class _MihBusinessQrCodeState extends State { mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - FutureBuilder( - future: futureImageUrl, - builder: (context, asyncSnapshot) { - if (asyncSnapshot.connectionState == - ConnectionState.done && - asyncSnapshot.hasData) { - if (asyncSnapshot.requireData != "" || - asyncSnapshot.requireData.isNotEmpty) { - return MihCircleAvatar( - imageFile: CachedNetworkImageProvider( - asyncSnapshot.requireData), - width: profilePictureWidth, - expandable: true, - editable: false, - fileNameController: TextEditingController(), - userSelectedfile: file, - frameColor: MihColors.primary(), - backgroundColor: MihColors.secondary(), - onChange: () {}, - ); - } else { - return Icon( - MihIcons.mihIDontKnow, - size: profilePictureWidth, - color: MihColors.primary(), - ); - } - } else { - return Icon( - MihIcons.mihRing, - size: profilePictureWidth, - color: MihColors.primary(), - ); - } - }, - ), + widget.business == null + ? MihCircleAvatar( + imageFile: profileprovider.businessProfilePicture, + width: profilePictureWidth, + expandable: true, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: MihColors.primary(), + backgroundColor: MihColors.secondary(), + onChange: () {}, + ) + : FutureBuilder( + future: futureImageUrl, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == + ConnectionState.done && + asyncSnapshot.hasData) { + if (asyncSnapshot.requireData != "" || + asyncSnapshot.requireData.isNotEmpty) { + return MihCircleAvatar( + imageFile: CachedNetworkImageProvider( + asyncSnapshot.requireData), + width: profilePictureWidth, + expandable: true, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: MihColors.primary(), + backgroundColor: MihColors.secondary(), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.mihIDontKnow, + size: profilePictureWidth, + color: MihColors.primary(), + ); + } + } else { + return Icon( + MihIcons.mihRing, + size: profilePictureWidth, + color: MihColors.primary(), + ); + } + }, + ), FittedBox( child: Text( business.Name, diff --git a/mih_ui/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart b/mih_ui/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart index 222f8296..618b6e0b 100644 --- a/mih_ui/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart +++ b/mih_ui/lib/mih_packages/mzansi_profile/business_profile/package_tools/mih_business_reviews.dart @@ -231,7 +231,7 @@ class _MihBusinessReviewsState extends State { ); } } else { - return Center(child: Text('Error')); + return Center(child: Text('Error: MIH in Offline Mode')); } }); } diff --git a/mih_ui/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart b/mih_ui/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart index df45d03e..79f5dfc2 100644 --- a/mih_ui/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart +++ b/mih_ui/lib/mih_packages/mzansi_profile/personal_profile/mzansi_profile.dart @@ -17,32 +17,32 @@ class MzansiProfile extends StatefulWidget { } class _MzansiProfileState extends State { - bool _isLoadingInitialData = true; + // bool _isLoadingInitialData = true; late final MihPersonalProfile _personalProfile; late final MihPersonalQrCode _personalQrCode; late final MihPersonalSettings _personalSettings; - Future _loadInitialData() async { - MzansiProfileProvider mzansiProfileProvider = - context.read(); - mzansiProfileProvider.loadCachedProfileState(); - if (mzansiProfileProvider.user == null) { - mzansiProfileProvider.syncWithCloudPipeline(); - } - setState(() { - _isLoadingInitialData = false; - }); - } - + // Future _loadInitialData() async { + // MzansiProfileProvider mzansiProfileProvider = + // context.read(); + // if (mzansiProfileProvider.user == null) { + // mzansiProfileProvider.loadCachedProfileState(); + // mzansiProfileProvider.syncWithMihServerData(); + // } + // setState(() { + // _isLoadingInitialData = false; + // }); + // } + // @override void initState() { super.initState(); _personalProfile = const MihPersonalProfile(); _personalQrCode = const MihPersonalQrCode(user: null); _personalSettings = const MihPersonalSettings(); - WidgetsBinding.instance.addPostFrameCallback((_) { - _loadInitialData(); - }); + // WidgetsBinding.instance.addPostFrameCallback((_) { + // _loadInitialData(); + // }); } @override @@ -50,13 +50,13 @@ class _MzansiProfileState extends State { return Consumer( builder: (BuildContext context, MzansiProfileProvider profileProvider, Widget? child) { - if (_isLoadingInitialData) { - return Scaffold( - body: Center( - child: Mihloadingcircle(), - ), - ); - } + // if (_isLoadingInitialData) { + // return Scaffold( + // body: Center( + // child: Mihloadingcircle(), + // ), + // ); + // } return MihPackage( packageActionButton: getAction(), packageTools: getTools(), diff --git a/mih_ui/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_qr_code.dart b/mih_ui/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_qr_code.dart index b9f86d4f..c01110ef 100644 --- a/mih_ui/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_qr_code.dart +++ b/mih_ui/lib/mih_packages/mzansi_profile/personal_profile/package_tools/mih_personal_qr_code.dart @@ -174,6 +174,8 @@ class _MihPersonalQrCodeState extends State { } Widget displayPersonalQRCode(double profilePictureWidth) { + MzansiProfileProvider profileProvider = + context.read(); return Screenshot( controller: screenshotController, child: Material( @@ -192,42 +194,54 @@ class _MihPersonalQrCodeState extends State { mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ - FutureBuilder( - future: futureImageUrl, - builder: (context, asyncSnapshot) { - if (asyncSnapshot.connectionState == - ConnectionState.done && - asyncSnapshot.hasData) { - if (asyncSnapshot.requireData != "" || - asyncSnapshot.requireData.isNotEmpty) { - return MihCircleAvatar( - imageFile: CachedNetworkImageProvider( - asyncSnapshot.requireData), - width: profilePictureWidth, - expandable: true, - editable: false, - fileNameController: TextEditingController(), - userSelectedfile: file, - frameColor: MihColors.primary(), - backgroundColor: MihColors.secondary(), - onChange: () {}, - ); - } else { - return Icon( - MihIcons.mihIDontKnow, - size: profilePictureWidth, - color: MihColors.primary(), - ); - } - } else { - return Icon( - MihIcons.mihRing, - size: profilePictureWidth, - color: MihColors.primary(), - ); - } - }, - ), + widget.user == null + ? MihCircleAvatar( + imageFile: profileProvider.userProfilePicture, + width: profilePictureWidth, + expandable: true, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: MihColors.primary(), + backgroundColor: MihColors.secondary(), + onChange: () {}, + ) + : FutureBuilder( + future: futureImageUrl, + builder: (context, asyncSnapshot) { + if (asyncSnapshot.connectionState == + ConnectionState.done && + asyncSnapshot.hasData) { + if (asyncSnapshot.requireData != "" || + asyncSnapshot.requireData.isNotEmpty) { + return MihCircleAvatar( + imageFile: CachedNetworkImageProvider( + asyncSnapshot.requireData), + width: profilePictureWidth, + expandable: true, + editable: false, + fileNameController: TextEditingController(), + userSelectedfile: file, + frameColor: MihColors.primary(), + backgroundColor: MihColors.secondary(), + onChange: () {}, + ); + } else { + return Icon( + MihIcons.mihIDontKnow, + size: profilePictureWidth, + color: MihColors.primary(), + ); + } + } else { + return Icon( + MihIcons.mihRing, + size: profilePictureWidth, + color: MihColors.primary(), + ); + } + }, + ), FittedBox( child: Text( user.username, diff --git a/mih_ui/lib/mih_providers/mzansi_profile_provider.dart b/mih_ui/lib/mih_providers/mzansi_profile_provider.dart index 312b60b0..9e2c7455 100644 --- a/mih_ui/lib/mih_providers/mzansi_profile_provider.dart +++ b/mih_ui/lib/mih_providers/mzansi_profile_provider.dart @@ -1,5 +1,6 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; +import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/mih_hive/mzansi_profile_hive_data.dart'; import 'package:mzansi_innovation_hub/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_objects/business.dart'; @@ -29,6 +30,8 @@ class MzansiProfileProvider extends ChangeNotifier { bool hideBusinessUserDetails; List personalLinks = []; List businessLinks = []; + final GlobalKey refreshIndicatorKey = + GlobalKey(); MzansiProfileProvider( this._hiveData, { @@ -59,14 +62,24 @@ class MzansiProfileProvider extends ChangeNotifier { businessUserSignature = CachedNetworkImageProvider(cachedSigUrl); } + employeeList = _hiveData.getCachedBusinessEmployees(); + personalLinks = _hiveData.getCachedPersonalProfileLinks(); + businessLinks = _hiveData.getCachedBusinessProfileLinks(); + + KenLogger.success("Mzansi Profile Loaded from Cache"); notifyListeners(); } - Future syncWithCloudPipeline() async { - await _hiveData.syncProfileDataWithServer(); + Future syncWithMihServerData() async { + bool success = await _hiveData.syncProfileDataWithServer(); loadCachedProfileState(); + return success; + } + + void triggerRefresh() { + refreshIndicatorKey.currentState?.show(); } void reset() { diff --git a/mih_ui/lib/mih_services/mih_business_employee_services.dart b/mih_ui/lib/mih_services/mih_business_employee_services.dart index 2895e0c0..682e5ad6 100644 --- a/mih_ui/lib/mih_services/mih_business_employee_services.dart +++ b/mih_ui/lib/mih_services/mih_business_employee_services.dart @@ -25,6 +25,19 @@ class MihBusinessEmployeeServices { return response.statusCode; } + Future> fetchEmployeesV2(String business_id) async { + final response = await http.get(Uri.parse( + "${AppEnviroment.baseApiUrl}/business-user/employees/${business_id}")); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List employeeList = List.from( + l.map((model) => BusinessEmployee.fromJson(model))); + return employeeList; + } else { + throw Exception('failed to load employees'); + } + } + Future addEmployee( MzansiProfileProvider provider, AppUser newEmployee, diff --git a/mih_ui/lib/mih_services/mih_profile_links_service.dart b/mih_ui/lib/mih_services/mih_profile_links_service.dart index 6823a7c7..0402646f 100644 --- a/mih_ui/lib/mih_services/mih_profile_links_service.dart +++ b/mih_ui/lib/mih_services/mih_profile_links_service.dart @@ -89,6 +89,21 @@ class MihProfileLinksServices { } } + static Future> getBusinessProfileLinksV2( + String business_id, + ) async { + final response = await http.get(Uri.parse( + "${AppEnviroment.baseApiUrl}/profile-links/business/$business_id")); + if (response.statusCode == 200) { + Iterable l = jsonDecode(response.body); + List myLinks = + List.from(l.map((model) => ProfileLink.fromJson(model))); + return myLinks; + } else { + throw Exception('failed to fecth user profile links'); + } + } + static Future deleteProfileLink( MzansiProfileProvider profileProvider, int idprofile_links,