switch to new image api strat and fix onboarding cache strat

This commit is contained in:
yaso 2026-07-07 14:30:58 +02:00
parent 48b434dad9
commit a5bdee892c
39 changed files with 540 additions and 791 deletions

View file

@ -42,6 +42,7 @@ void main() async {
await Hive.openBox<ProfileLink>('personal_profile_links_box'); await Hive.openBox<ProfileLink>('personal_profile_links_box');
await Hive.openBox<ProfileLink>('business_profile_links_box'); await Hive.openBox<ProfileLink>('business_profile_links_box');
await Hive.openBox<BusinessEmployee>('business_employees_box'); await Hive.openBox<BusinessEmployee>('business_employees_box');
await Hive.openBox<Map>('profile_modifications_queue');
// Mzansi Wallet Data // Mzansi Wallet Data
await Hive.openBox<MIHLoyaltyCard>('loyalty_card_box'); await Hive.openBox<MIHLoyaltyCard>('loyalty_card_box');
await Hive.openBox<MIHLoyaltyCard>('fav_loyalty_card_box'); await Hive.openBox<MIHLoyaltyCard>('fav_loyalty_card_box');

View file

@ -9,6 +9,16 @@ class AboutMihHiveData {
static const String kUserCountKey = 'current_user_count'; static const String kUserCountKey = 'current_user_count';
static const String kBusinessCountKey = 'current_business_count'; static const String kBusinessCountKey = 'current_business_count';
// Clear Local Cache
Future<void> clearAboutMIHCache() async {
try {
await _mihUserBusinessCountBox.clear();
KenLogger.success("Cleared Local About MIH Cache.");
} catch (error) {
KenLogger.error("Failed to clear local about mih cache.");
}
}
// Get Data from local storage // Get Data from local storage
int? getcachedUserCount() => _mihUserBusinessCountBox.get(kUserCountKey); int? getcachedUserCount() => _mihUserBusinessCountBox.get(kUserCountKey);
int? getcachedBusinessCount() => int? getcachedBusinessCount() =>

View file

@ -26,6 +26,25 @@ class MzansiProfileHiveData {
Hive.box<ProfileLink>('business_profile_links_box'); Hive.box<ProfileLink>('business_profile_links_box');
final Box<BusinessEmployee> _businessEmployeesBox = final Box<BusinessEmployee> _businessEmployeesBox =
Hive.box<BusinessEmployee>('business_Employees_box'); Hive.box<BusinessEmployee>('business_Employees_box');
final Box<Map> _modificationsQueue =
Hive.box<Map>('profile_modifications_queue');
// Set offline data
Future<void> clearProfileCache() async {
try {
await _userBox.clear();
await _businessBox.clear();
await _businessUserBox.clear();
await _userConsentBox.clear();
await _personalProfileLinksBox.clear();
await _businessProfileLinksBox.clear();
await _businessEmployeesBox.clear();
await _modificationsQueue.clear();
KenLogger.success("Cleared Local Profile Cache.");
} catch (error) {
KenLogger.error("Failed to clear local profile cache.");
}
}
static const String kUserKey = 'current_user'; static const String kUserKey = 'current_user';
static const String kBusinessKey = 'current_business'; static const String kBusinessKey = 'current_business';
@ -144,4 +163,58 @@ class MzansiProfileHiveData {
// KenLogger.warning("App operating offline mode. Sync paused: $error"); // KenLogger.warning("App operating offline mode. Sync paused: $error");
} }
} }
// Set Offline Data
Future<bool> addUserConsentLocally(UserConsent newConsent) async {
try {
await _userConsentBox.put(kConsentKey, newConsent);
KenLogger.success("Consent Saved Locally.");
return true;
} catch (error) {
return false;
}
}
// Modification Processing
Future<void> queuAddConsentModification(UserConsent newConsent) async {
await _modificationsQueue.add({
'action': 'ADD',
'type': 'CONSENT',
'payload': newConsent,
});
KenLogger.success("Add Consent Queues for Online Sync");
}
Future<bool> processModificationsQueue() async {
if (_modificationsQueue.isEmpty) {
return true;
}
final List<dynamic> queueKeys = _modificationsQueue.keys.toList();
for (var taskKey in queueKeys) {
final task = _modificationsQueue.get(taskKey);
if (task == null) {
continue;
}
final String action = task['action'];
final String type = task['type'];
if (type == 'CONSENT') {
final UserConsent consentTask = task['payload'];
if (action == 'ADD') {
final responseCode =
await MihUserConsentServices().insertUserConsentStatusV2(
consentTask,
);
if (responseCode != null && responseCode == 201) {
await _modificationsQueue.delete(taskKey);
KenLogger.success("Add User Consent to MIH Server");
}
}
}
}
return true;
}
bool isModificationsNotEmpty() {
return _modificationsQueue.values.toList().isNotEmpty;
}
} }

View file

@ -13,6 +13,18 @@ class MzansiWalletHiveData {
final Box<Map> _modificationsQueue = final Box<Map> _modificationsQueue =
Hive.box<Map>('wallet_modifications_queue'); Hive.box<Map>('wallet_modifications_queue');
// Set offline data
Future<void> clearWalletCache() async {
try {
await _loyaltyCardBox.clear();
await _favLoyaltyCardBox.clear();
await _modificationsQueue.clear();
KenLogger.success("Cleared Local Wallet Cache.");
} catch (error) {
KenLogger.error("Failed to clear local wallet cache.");
}
}
// Get Offline Data // Get Offline Data
List<MIHLoyaltyCard> getCachedLoyaltyCards() { List<MIHLoyaltyCard> getCachedLoyaltyCards() {
final cards = _loyaltyCardBox.values.toList(); final cards = _loyaltyCardBox.values.toList();
@ -204,8 +216,6 @@ class MzansiWalletHiveData {
} }
final String action = task['action']; final String action = task['action'];
final MIHLoyaltyCard taskCard = task['payload']; final MIHLoyaltyCard taskCard = task['payload'];
KenLogger.warning(
"Card Details: id=${taskCard.idloyalty_cards}, shop=${taskCard.shop_name}, Nunber=${taskCard.card_number}, offline_id=${taskCard.offline_id}");
if (action == 'ADD') { if (action == 'ADD') {
dynamic deleteCardTaskKey; dynamic deleteCardTaskKey;
for (var entry in _modificationsQueue.toMap().entries) { for (var entry in _modificationsQueue.toMap().entries) {

View file

@ -539,7 +539,6 @@ class _MihBusinessCardState extends State<MihBusinessCard> {
} }
directoryProvider.setSearchedBusinesses( directoryProvider.setSearchedBusinesses(
searchedBusinesses: businessSearchResults, searchedBusinesses: businessSearchResults,
businessesImagesUrl: busImagesUrl,
); );
setState(() { setState(() {
_businessReviewFuture = getUserReview(); _businessReviewFuture = getUserReview();

View file

@ -518,15 +518,8 @@ class _MihBusinessCardV2State extends State<MihBusinessCardV2> {
businessSearchResults = await MihBusinessDetailsServices() businessSearchResults = await MihBusinessDetailsServices()
.searchBusinesses(directoryProvider.searchTerm, .searchBusinesses(directoryProvider.searchTerm,
directoryProvider.businessTypeFilter, context); directoryProvider.businessTypeFilter, context);
Map<String, Future<String>> busImagesUrl = {};
Future<String> businessLogoUrl;
for (var bus in businessSearchResults) {
businessLogoUrl = MihFileApi.getMinioFileUrl(bus.logo_path);
busImagesUrl[bus.business_id] = businessLogoUrl;
}
directoryProvider.setSearchedBusinesses( directoryProvider.setSearchedBusinesses(
searchedBusinesses: businessSearchResults, searchedBusinesses: businessSearchResults,
businessesImagesUrl: busImagesUrl,
); );
setState(() { setState(() {
_businessReviewFuture = getUserReview(); _businessReviewFuture = getUserReview();

View file

@ -54,7 +54,8 @@ class _MihBusinessProfilePreviewState extends State<MihBusinessProfilePreview> {
size: profilePictureWidth, size: profilePictureWidth,
color: MihColors.secondary(), color: MihColors.secondary(),
) )
: widget.imageFile == null : widget.business.logo_path.endsWith('/') ||
widget.business.logo_path == ''
? Icon( ? Icon(
MihIcons.mihIDontKnow, MihIcons.mihIDontKnow,
size: profilePictureWidth, size: profilePictureWidth,

View file

@ -36,7 +36,8 @@ class _MihPersonalProfilePreviewState extends State<MihPersonalProfilePreview> {
size: profilePictureWidth, size: profilePictureWidth,
color: MihColors.secondary(), color: MihColors.secondary(),
) )
: widget.imageFile == null : widget.user.pro_pic_path.endsWith('/') ||
widget.user.pro_pic_path == ""
? Icon( ? Icon(
MihIcons.mihIDontKnow, MihIcons.mihIDontKnow,
size: profilePictureWidth, size: profilePictureWidth,

View file

@ -1,18 +1,13 @@
import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart'; import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/main.dart'; import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_providers/mih_authentication_provider.dart'; import 'package:mzansi_innovation_hub/mih_providers/mih_authentication_provider.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.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_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_authentication_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:supertokens_flutter/http.dart' as http;
import 'package:supertokens_flutter/supertokens.dart';
class MihRegister extends StatefulWidget { class MihRegister extends StatefulWidget {
const MihRegister({ const MihRegister({
@ -31,142 +26,11 @@ class _MihRegisterState extends State<MihRegister> {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
final baseAPI = AppEnviroment.baseApiUrl; final baseAPI = AppEnviroment.baseApiUrl;
Future<void> addUserAPICall(String email, String uid) async {
//await getOfficeIdByUser(docOfficeIdApiUrl + widget.userEmail);
//print(futureDocOfficeId.toString());
await MihUserServices().createUser(
email,
uid,
context,
);
// var response = await http.post(
// Uri.parse("$baseAPI/user/insert/"),
// headers: <String, String>{
// "Content-Type": "application/json; charset=UTF-8"
// },
// body: jsonEncode(<String, dynamic>{
// "email": email,
// "app_id": uid,
// }),
// );
// if (response.statusCode == 201) {
// Navigator.of(context).pushNamedAndRemoveUntil(
// '/',
// (route) => false,
// arguments: AuthArguments(
// true,
// true,
// ),
// );
// // signUpSuccess();
// // setState(() {
// // successfulSignUp = true;
// // });
// } else {
// internetConnectionPopUp();
// }
}
Future<void> signUserUp() async {
context.read<MzansiProfileProvider>().reset();
if (!validEmail()) {
MihAlertServices().invalidEmailAlert(context);
} else if (passwordController.text != confirmPasswordController.text) {
MihAlertServices().passwordMatchAlert(context);
} else {
//var _backgroundColor = Colors.transparent;
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
try {
Uri uri = Uri.parse(
"$baseAPI/auth/emailpassword/email/exists?email=${emailController.text}");
//print("Here");
var response = await http.get(uri);
//print(response.body);
//print("response 1: ${response.statusCode}");
if (response.statusCode == 200) {
var userExists = jsonDecode(response.body);
if (userExists["exists"]) {
Navigator.of(context).pop();
MihAlertServices().emailExistsAlert(context);
} else {
var response2 = await http.post(
Uri.parse("$baseAPI/auth/signup"),
body:
'{"formFields": [{"id": "email","value": "${emailController.text}"}, {"id": "password","value": "${passwordController.text}"}]}',
headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
},
);
//print("response 2: ${response2.statusCode}");
if (response2.statusCode == 200) {
//print("response 2: ${response2.body}");
var userCreated = jsonDecode(response2.body);
//print("Created user $userCreated");
if (userCreated["status"] == "OK") {
//print("Here1");
//Creat user in db
String uid = await SuperTokens.getUserId();
//print("uid: $uid");
addUserAPICall(emailController.text, uid);
Navigator.of(context).pop();
//print("Here1");
} else if (userCreated["status"] == "FIELD_ERROR") {
Navigator.of(context).pop();
MihAlertServices().passwordRequirementAlert(context);
} else {
Navigator.of(context).pop();
MihAlertServices().internetConnectionAlert(context);
}
}
}
}
} on Exception catch (error) {
Navigator.of(context).pop();
loginError(error.toString());
emailController.clear();
passwordController.clear();
confirmPasswordController.clear();
}
}
}
void submitFormInput() async { void submitFormInput() async {
await signUserUp(); await MihAuthenticationServices().signUserUp(
} emailController.text,
passwordController.text,
bool validEmail() { confirmPasswordController.text,
String text = emailController.text;
var regex = RegExp(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$');
return regex.hasMatch(text);
}
void loginError(error) {
MihAlertServices().errorAdvancedAlert(
"Sign Up Error",
"An error occurred while signing up: $error Please try again later.",
[
MihButton(
onPressed: () {
Navigator.of(context).pop();
},
buttonColor: MihColors.secondary(),
width: 200,
child: Text(
"Dismiss",
style: TextStyle(
color: MihColors.primary(),
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
],
context, context,
); );
} }

View file

@ -30,8 +30,7 @@ class _MIHAppDrawerState extends State<MIHAppDrawer> {
final proPicController = TextEditingController(); final proPicController = TextEditingController();
late Widget profilePictureLoaded; late Widget profilePictureLoaded;
void resetProviders() { Future<void> clearCacheAndProviders() async {
context.read<AboutMihProvider>().reset();
context.read<MihAccessControllsProvider>().reset(); context.read<MihAccessControllsProvider>().reset();
context.read<MihAuthenticationProvider>().reset(); context.read<MihAuthenticationProvider>().reset();
context.read<MihBannerAdProvider>().reset(); context.read<MihBannerAdProvider>().reset();
@ -40,8 +39,10 @@ class _MIHAppDrawerState extends State<MIHAppDrawer> {
context.read<MihMineSweeperProvider>().reset(); context.read<MihMineSweeperProvider>().reset();
context.read<MzansiAiProvider>().reset(); context.read<MzansiAiProvider>().reset();
context.read<MzansiDirectoryProvider>().reset(); context.read<MzansiDirectoryProvider>().reset();
context.read<MzansiWalletProvider>().reset();
context.read<PatientManagerProvider>().reset(); context.read<PatientManagerProvider>().reset();
await context.read<AboutMihProvider>().clearAboutMihCacheAndProvider();
await context.read<MzansiWalletProvider>().clearWalletCacheAndProvider();
await context.read<MzansiProfileProvider>().clearProfileCacheAndProvider();
} }
Future<bool> signOut() async { Future<bool> signOut() async {
@ -187,32 +188,6 @@ class _MIHAppDrawerState extends State<MIHAppDrawer> {
), ),
), ),
), ),
// ListTile(
// title: Row(
// mainAxisSize: MainAxisSize.max,
// children: [
// Icon(
// Icons.home_outlined,
// color:
// MihColors.secondary(),
// ),
// 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( Expanded(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
@ -291,8 +266,7 @@ class _MIHAppDrawerState extends State<MIHAppDrawer> {
}); });
if (await SuperTokens.doesSessionExist() == if (await SuperTokens.doesSessionExist() ==
false) { false) {
resetProviders(); await clearCacheAndProviders();
await Future.delayed(Duration.zero);
if (context.mounted) { if (context.mounted) {
context.goNamed( context.goNamed(
'mihHome', 'mihHome',
@ -313,21 +287,6 @@ class _MIHAppDrawerState extends State<MIHAppDrawer> {
height: 30, height: 30,
child: InkWell( child: InkWell(
onTap: () { 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"); context.goNamed("aboutMih");
}, },
child: Icon( child: Icon(
@ -335,27 +294,6 @@ class _MIHAppDrawerState extends State<MIHAppDrawer> {
color: MihColors.primary(), color: MihColors.primary(),
), ),
), ),
// 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.primary(),
// size: 35,
// ),
// ),
), ),
], ],
); );

View file

@ -16,10 +16,11 @@ class MihUserConsentWindow extends StatefulWidget {
} }
class _MihUserConsentWindowState extends State<MihUserConsentWindow> { class _MihUserConsentWindowState extends State<MihUserConsentWindow> {
void createOrUpdateAccpetance(MzansiProfileProvider mzansiProfileProvider) { void createOrUpdateAccpetance(
MzansiProfileProvider mzansiProfileProvider) async {
UserConsent? userConsent = mzansiProfileProvider.userConsent; UserConsent? userConsent = mzansiProfileProvider.userConsent;
userConsent != null if (userConsent != null) {
? MihUserConsentServices() MihUserConsentServices()
.updateUserConsentStatus( .updateUserConsentStatus(
DateTime.now().toIso8601String(), DateTime.now().toIso8601String(),
DateTime.now().toIso8601String(), DateTime.now().toIso8601String(),
@ -42,17 +43,15 @@ class _MihUserConsentWindowState extends State<MihUserConsentWindow> {
), ),
); );
} }
}) });
: MihUserConsentServices() } else {
.insertUserConsentStatus( bool success = await mzansiProfileProvider.addUserConsent(UserConsent(
DateTime.now().toIso8601String(), app_id: mzansiProfileProvider.user!.app_id,
DateTime.now().toIso8601String(), privacy_policy_accepted: DateTime.now(),
mzansiProfileProvider, terms_of_services_accepted: DateTime.now(),
context, ));
) if (success) {
.then((value) { context.pop();
if (value == 201) {
context.goNamed("mihHome");
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
MihSnackBar( MihSnackBar(
child: Text("Thank you for accepting our Policies"), child: Text("Thank you for accepting our Policies"),
@ -65,7 +64,7 @@ class _MihUserConsentWindowState extends State<MihUserConsentWindow> {
), ),
); );
} }
}); }
} }
@override @override

View file

@ -45,7 +45,8 @@ class _MihHomeState extends State<MihHome> {
mzansiProfileProvider.loadCachedProfileState(); mzansiProfileProvider.loadCachedProfileState();
if (mzansiProfileProvider.user == null) { if (mzansiProfileProvider.user == null) {
await mzansiProfileProvider.syncWithMihServerData(); await mzansiProfileProvider.syncWithMihServerData();
} else { }
if(mzansiProfileProvider.isLocalModificationsPending()){
mzansiProfileProvider.syncWithMihServerData(); mzansiProfileProvider.syncWithMihServerData();
} }
} }

View file

@ -209,15 +209,6 @@ class _MihPersonalHomeState extends State<MihPersonalHome>
void initState() { void initState() {
super.initState(); super.initState();
searchController.addListener(searchPackage); searchController.addListener(searchPackage);
MzansiProfileProvider profileProvider =
context.read<MzansiProfileProvider>();
if (profileProvider.user == null || profileProvider.user?.username == "") {
personalPackagesMap = setNerUserPersonalPackage();
autoNavToProfile();
} else {
personalPackagesMap = setPersonalPackagesMap(profileProvider);
}
searchPackage();
} }
@override @override
@ -237,6 +228,14 @@ class _MihPersonalHomeState extends State<MihPersonalHome>
return Consumer2<MzansiProfileProvider, MzansiAiProvider>( return Consumer2<MzansiProfileProvider, MzansiAiProvider>(
builder: (BuildContext context, MzansiProfileProvider profileProvider, builder: (BuildContext context, MzansiProfileProvider profileProvider,
MzansiAiProvider mzansiAiProvider, Widget? child) { MzansiAiProvider mzansiAiProvider, Widget? child) {
if (profileProvider.user == null ||
profileProvider.user?.username == "") {
personalPackagesMap = setNerUserPersonalPackage();
autoNavToProfile();
} else {
personalPackagesMap = setPersonalPackagesMap(profileProvider);
}
searchPackage();
return Column( return Column(
children: [ children: [
Visibility( Visibility(

View file

@ -4,6 +4,7 @@ import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart'; import 'package:mzansi_innovation_hub/mih_package_components/mih_circle_avatar.dart';
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart'; import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class BuildMinesweeperLeaderboardList extends StatefulWidget { class BuildMinesweeperLeaderboardList extends StatefulWidget {
@ -43,24 +44,6 @@ class _BuildMinesweeperLeaderboardListState
}, },
itemCount: mineSweeperProvider.leaderboard!.length, itemCount: mineSweeperProvider.leaderboard!.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return FutureBuilder(
future: mineSweeperProvider.leaderboardUserPicturesUrl[index],
builder: (context, asyncSnapshot) {
ImageProvider<Object>? imageFile;
bool loading = true;
if (asyncSnapshot.connectionState == ConnectionState.done) {
loading = false;
if (asyncSnapshot.hasData) {
imageFile = asyncSnapshot.requireData != ""
? CachedNetworkImageProvider(
asyncSnapshot.requireData)
: null;
} else {
imageFile = null;
}
} else {
imageFile = null;
}
return Padding( return Padding(
padding: EdgeInsets.symmetric(horizontal: width / 20), padding: EdgeInsets.symmetric(horizontal: width / 20),
child: Row( child: Row(
@ -73,13 +56,10 @@ class _BuildMinesweeperLeaderboardListState
), ),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
loading mineSweeperProvider.leaderboard![index].proPicUrl
? Icon( .endsWith('/') ||
MihIcons.mihRing, mineSweeperProvider.leaderboard![index].proPicUrl ==
size: 80, ''
color: MihColors.secondary(),
)
: imageFile == null
? Icon( ? Icon(
MihIcons.mihIDontKnow, MihIcons.mihIDontKnow,
size: 80, size: 80,
@ -87,7 +67,9 @@ class _BuildMinesweeperLeaderboardListState
) )
: MihCircleAvatar( : MihCircleAvatar(
key: UniqueKey(), key: UniqueKey(),
imageFile: imageFile, imageFile: CachedNetworkImageProvider(
MihFileApi.getMinioFileUrlV2(mineSweeperProvider
.leaderboard![index].proPicUrl)),
width: 80, width: 80,
expandable: true, expandable: true,
editable: false, editable: false,
@ -125,7 +107,6 @@ class _BuildMinesweeperLeaderboardListState
], ],
), ),
); );
});
}, },
); );
}, },

View file

@ -1,10 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart'; import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart'; import 'package:mzansi_innovation_hub/mih_providers/mih_mine_sweeper_provider.dart';
import 'package:mzansi_innovation_hub/mih_packages/mine_sweeper/builders/build_minesweeper_leaderboard_list.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_minesweeper_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -24,16 +21,7 @@ class _MihMineSweeperLeaderBoardState extends State<MihMineSweeperLeaderBoard> {
MihMineSweeperProvider mineSweeperProvider = MihMineSweeperProvider mineSweeperProvider =
context.read<MihMineSweeperProvider>(); context.read<MihMineSweeperProvider>();
filterController.text = mineSweeperProvider.difficulty; filterController.text = mineSweeperProvider.difficulty;
KenLogger.success("getting data");
await MihMinesweeperServices().getTop20Leaderboard(mineSweeperProvider); await MihMinesweeperServices().getTop20Leaderboard(mineSweeperProvider);
List<Future<String>> userPicturesUrl = [];
Future<String> userPicUrl;
for (final ranking in mineSweeperProvider.leaderboard!) {
userPicUrl = MihFileApi.getMinioFileUrl(ranking.proPicUrl);
userPicturesUrl.add(userPicUrl);
}
mineSweeperProvider.setLeaderboardUserPictures(
leaderboardUserPicturesUrl: userPicturesUrl);
setState(() { setState(() {
isLoading = false; isLoading = false;
}); });

View file

@ -26,10 +26,8 @@ class _MihMineSweeperLeaderBoardState extends State<MyScoreBoard> {
MihMineSweeperProvider mineSweeperProvider = MihMineSweeperProvider mineSweeperProvider =
context.read<MihMineSweeperProvider>(); context.read<MihMineSweeperProvider>();
filterController.text = mineSweeperProvider.difficulty; filterController.text = mineSweeperProvider.difficulty;
KenLogger.success("getting data");
await MihMinesweeperServices() await MihMinesweeperServices()
.getMyScoreboard(profileProvider, mineSweeperProvider); .getMyScoreboard(profileProvider, mineSweeperProvider);
KenLogger.success("${mineSweeperProvider.myScoreboard}");
} }
void refreshLeaderBoard( void refreshLeaderBoard(

View file

@ -5,6 +5,7 @@ import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_business_profile_preview.dart'; import 'package:mzansi_innovation_hub/mih_package_components/mih_business_profile_preview.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class BuildBusinessSearchResultsList extends StatefulWidget { class BuildBusinessSearchResultsList extends StatefulWidget {
@ -27,8 +28,6 @@ class _BuildBusinessSearchResultsListState
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider, builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
Widget? child) { Widget? child) {
return ListView.separated( return ListView.separated(
// shrinkWrap: true,
// physics: const NeverScrollableScrollPhysics(),
itemCount: widget.businessList.length, itemCount: widget.businessList.length,
separatorBuilder: (BuildContext context, index) { separatorBuilder: (BuildContext context, index) {
return Divider( return Divider(
@ -54,32 +53,14 @@ class _BuildBusinessSearchResultsListState
// vertical: 5, // vertical: 5,
horizontal: 25, horizontal: 25,
), ),
child: FutureBuilder( child: MihBusinessProfilePreview(
future: directoryProvider.busSearchImagesUrl![
widget.businessList[index].business_id],
builder: (context, asyncSnapshot) {
ImageProvider<Object>? imageFile;
bool loading = true;
if (asyncSnapshot.connectionState ==
ConnectionState.done) {
loading = false;
if (asyncSnapshot.hasData) {
imageFile = asyncSnapshot.requireData != ""
? CachedNetworkImageProvider(
asyncSnapshot.requireData)
: null;
} else {
imageFile = null;
}
} else {
imageFile = null;
}
return MihBusinessProfilePreview(
business: widget.businessList[index], business: widget.businessList[index],
imageFile: imageFile, imageFile: CachedNetworkImageProvider(
loading: loading, MihFileApi.getMinioFileUrlV2(
); widget.businessList[index].logo_path),
}), ),
loading: false,
),
), ),
), ),
); );

View file

@ -5,6 +5,7 @@ import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/mih_objects/business.dart'; import 'package:mzansi_innovation_hub/mih_objects/business.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_business_profile_preview.dart'; import 'package:mzansi_innovation_hub/mih_package_components/mih_business_profile_preview.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class BuildFavouriteBusinessesList extends StatefulWidget { class BuildFavouriteBusinessesList extends StatefulWidget {
@ -59,32 +60,15 @@ class _BuildFavouriteBusinessesListState
padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
horizontal: 25, horizontal: 25,
), ),
child: FutureBuilder( child: MihBusinessProfilePreview(
future: directoryProvider.favBusImagesUrl![
widget.favouriteBusinesses[index]!.business_id],
builder: (context, asyncSnapshot) {
ImageProvider<Object>? imageFile;
bool loading = true;
if (asyncSnapshot.connectionState ==
ConnectionState.done) {
loading = false;
if (asyncSnapshot.hasData) {
imageFile = asyncSnapshot.requireData != ""
? CachedNetworkImageProvider(
asyncSnapshot.requireData)
: null;
} else {
imageFile = null;
}
} else {
imageFile = null;
}
return MihBusinessProfilePreview(
business: widget.favouriteBusinesses[index]!, business: widget.favouriteBusinesses[index]!,
imageFile: imageFile, imageFile: CachedNetworkImageProvider(
loading: loading, MihFileApi.getMinioFileUrlV2(
); widget.favouriteBusinesses[index]!.logo_path,
}), ),
),
loading: false,
),
), ),
), ),
); );

View file

@ -5,6 +5,7 @@ import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/mih_objects/app_user.dart'; import 'package:mzansi_innovation_hub/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_package_components/mih_personal_profile_preview.dart'; import 'package:mzansi_innovation_hub/mih_package_components/mih_personal_profile_preview.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart'; import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class BuildUserSearchResultsList extends StatefulWidget { class BuildUserSearchResultsList extends StatefulWidget {
@ -27,8 +28,6 @@ class _BuildUserSearchResultsListState
builder: (BuildContext context, MzansiDirectoryProvider directoryProvider, builder: (BuildContext context, MzansiDirectoryProvider directoryProvider,
Widget? child) { Widget? child) {
return ListView.separated( return ListView.separated(
// shrinkWrap: true,
// physics: const NeverScrollableScrollPhysics(),
itemCount: widget.userList.length, itemCount: widget.userList.length,
separatorBuilder: (BuildContext context, index) { separatorBuilder: (BuildContext context, index) {
return Divider( return Divider(
@ -53,32 +52,14 @@ class _BuildUserSearchResultsListState
// vertical: 5, // vertical: 5,
horizontal: 25, horizontal: 25,
), ),
child: FutureBuilder( child: MihPersonalProfilePreview(
future: directoryProvider
.userSearchImagesUrl![widget.userList[index].app_id],
builder: (context, asyncSnapshot) {
ImageProvider<Object>? imageFile;
bool loading = true;
if (asyncSnapshot.connectionState ==
ConnectionState.done) {
loading = false;
if (asyncSnapshot.hasData) {
imageFile = asyncSnapshot.requireData != ""
? CachedNetworkImageProvider(
asyncSnapshot.requireData)
: null;
} else {
imageFile = null;
}
} else {
imageFile = null;
}
return MihPersonalProfilePreview(
user: widget.userList[index], user: widget.userList[index],
imageFile: imageFile, imageFile: CachedNetworkImageProvider(
loading: loading, MihFileApi.getMinioFileUrlV2(
); widget.userList[index].pro_pic_path),
}), ),
loading: false,
),
), ),
), ),
); );

View file

@ -6,7 +6,6 @@ import 'package:mzansi_innovation_hub/mih_providers/mzansi_directory_provider.da
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_favourite_businesses_list.dart'; import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_favourite_businesses_list.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_directory_services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -37,20 +36,15 @@ class _MihFavouriteBusinessesState extends State<MihFavouriteBusinesses> {
directoryProvider, directoryProvider,
); );
List<Business> favBus = []; List<Business> favBus = [];
Map<String, Future<String>> favBusImages = {};
Future<String> businessLogoUrl;
for (var bus in directoryProvider.bookmarkedBusinesses) { for (var bus in directoryProvider.bookmarkedBusinesses) {
await MihBusinessDetailsServices() await MihBusinessDetailsServices()
.getBusinessDetailsByBusinessId(bus.business_id) .getBusinessDetailsByBusinessId(bus.business_id)
.then((business) async { .then((business) async {
favBus.add(business!); favBus.add(business!);
businessLogoUrl = MihFileApi.getMinioFileUrl(business.logo_path);
favBusImages[business.business_id] = businessLogoUrl;
}); });
} }
directoryProvider.setFavouriteBusinesses( directoryProvider.setFavouriteBusinesses(
businesses: favBus, businesses: favBus,
businessesImagesUrl: favBusImages,
); );
} }
} }

View file

@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart'; import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/mih_objects/app_user.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.dart';
@ -9,7 +8,6 @@ import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/bui
import 'package:mzansi_innovation_hub/mih_packages/mzansi_directory/builders/build_user_search_results_list.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_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_file_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -26,8 +24,6 @@ class _MihSearchMzansiState extends State<MihSearchMzansi> {
final TextEditingController mzansiSearchController = TextEditingController(); final TextEditingController mzansiSearchController = TextEditingController();
final TextEditingController businessTypeController = TextEditingController(); final TextEditingController businessTypeController = TextEditingController();
final FocusNode searchFocusNode = FocusNode(); final FocusNode searchFocusNode = FocusNode();
// late bool userSearch;
// Future<List<AppUser>?> futureUserSearchResults = Future.value();
List<AppUser> userSearchResults = []; List<AppUser> userSearchResults = [];
List<Business> businessSearchResults = []; List<Business> businessSearchResults = [];
late Future<List<String>> availableBusinessTypes; late Future<List<String>> availableBusinessTypes;
@ -51,9 +47,8 @@ class _MihSearchMzansiState extends State<MihSearchMzansi> {
} }
void clearAll(MzansiDirectoryProvider directoryProvider) { void clearAll(MzansiDirectoryProvider directoryProvider) {
directoryProvider directoryProvider.setSearchedBusinesses(searchedBusinesses: []);
.setSearchedBusinesses(searchedBusinesses: [], businessesImagesUrl: {}); directoryProvider.setSearchedUsers(searchedUsers: []);
directoryProvider.setSearchedUsers(searchedUsers: [], userImagesUrl: {});
directoryProvider.setSearchTerm(searchTerm: ""); directoryProvider.setSearchTerm(searchTerm: "");
setState(() { setState(() {
mzansiSearchController.clear(); mzansiSearchController.clear();
@ -73,19 +68,8 @@ class _MihSearchMzansiState extends State<MihSearchMzansi> {
directoryProvider.searchTerm.isNotEmpty) { directoryProvider.searchTerm.isNotEmpty) {
final userResults = await MihUserServices() final userResults = await MihUserServices()
.searchUsers(profileProvider, directoryProvider.searchTerm, context); .searchUsers(profileProvider, directoryProvider.searchTerm, context);
Map<String, Future<String>> userImages = {};
Future<String> usernProPicUrl;
for (var user in userResults) {
usernProPicUrl = MihFileApi.getMinioFileUrl(user.pro_pic_path);
userImages[user.app_id] = usernProPicUrl;
// != ""
// ? CachedNetworkImageProvider(usernProPicUrl)
// : null;
}
directoryProvider.setSearchedUsers( directoryProvider.setSearchedUsers(
searchedUsers: userResults, searchedUsers: userResults,
userImagesUrl: userImages,
); );
} else { } else {
List<Business>? businessSearchResults = []; List<Business>? businessSearchResults = [];
@ -98,18 +82,8 @@ class _MihSearchMzansiState extends State<MihSearchMzansi> {
.searchBusinesses(directoryProvider.searchTerm, .searchBusinesses(directoryProvider.searchTerm,
directoryProvider.businessTypeFilter, context); directoryProvider.businessTypeFilter, context);
} }
Map<String, Future<String>> busImagesUrl = {};
Future<String> businessLogoUrl;
for (var bus in businessSearchResults) {
businessLogoUrl = MihFileApi.getMinioFileUrl(bus.logo_path);
busImagesUrl[bus.business_id] = businessLogoUrl;
// != ""
// ? CachedNetworkImageProvider(businessLogoUrl)
// : null;
}
directoryProvider.setSearchedBusinesses( directoryProvider.setSearchedBusinesses(
searchedBusinesses: businessSearchResults, searchedBusinesses: businessSearchResults,
businessesImagesUrl: busImagesUrl,
); );
} }
setState(() { setState(() {

View file

@ -47,7 +47,6 @@ class _MihAddBookmarkAlertState extends State<MihAddBookmarkAlert> {
} }
directoryProvider.setFavouriteBusinesses( directoryProvider.setFavouriteBusinesses(
businesses: favBus, businesses: favBus,
businessesImagesUrl: favBusImages,
); );
} }

View file

@ -52,7 +52,6 @@ class _MihDeleteBookmarkAlertState extends State<MihDeleteBookmarkAlert> {
} }
directoryProvider.setFavouriteBusinesses( directoryProvider.setFavouriteBusinesses(
businesses: favBus, businesses: favBus,
businessesImagesUrl: favBusImages,
); );
} }

View file

@ -69,16 +69,11 @@ class _MihBusinessDetailsViewState extends State<MihBusinessDetailsView> {
: EdgeInsets.symmetric(horizontal: width * 0), : EdgeInsets.symmetric(horizontal: width * 0),
child: Column( child: Column(
children: [ children: [
FutureBuilder( MihCircleAvatar(
future: futureImageUrl,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState ==
ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "") {
return MihCircleAvatar(
imageFile: CachedNetworkImageProvider( imageFile: CachedNetworkImageProvider(
asyncSnapshot.requireData), MihFileApi.getMinioFileUrlV2(
directoryProvider.selectedBusiness!.logo_path),
),
width: profilePictureWidth, width: profilePictureWidth,
expandable: true, expandable: true,
editable: false, editable: false,
@ -87,40 +82,7 @@ class _MihBusinessDetailsViewState extends State<MihBusinessDetailsView> {
frameColor: MihColors.secondary(), frameColor: MihColors.secondary(),
backgroundColor: MihColors.primary(), backgroundColor: MihColors.primary(),
onChange: () {}, onChange: () {},
); ),
} else {
return Icon(
MihIcons.mihIDontKnow,
size: profilePictureWidth,
color: MihColors.secondary(),
);
}
} else {
return Icon(
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.secondary(),
);
}
}),
// Center(
// child: MihCircleAvatar(
// imageFile: widget.logoImage,
// width: 150,
// editable: false,
// fileNameController: fileNameController,
// userSelectedfile: imageFile,
// frameColor:
// MihColors.secondary(),
// backgroundColor:
// MihColors.primary(),
// onChange: (selectedfile) {
// setState(() {
// imageFile = selectedfile;
// });
// },
// ),
// ),
FittedBox( FittedBox(
child: Text( child: Text(
directoryProvider.selectedBusiness!.Name, directoryProvider.selectedBusiness!.Name,

View file

@ -1,5 +1,3 @@
import 'dart:io';
import 'package:cached_network_image/cached_network_image.dart'; import 'package:cached_network_image/cached_network_image.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:file_saver/file_saver.dart'; import 'package:file_saver/file_saver.dart';
@ -59,7 +57,7 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
String encodedData = String encodedData =
Uri.encodeComponent("$qrCodedata${business.business_id}"); Uri.encodeComponent("$qrCodedata${business.business_id}");
return "https://api.qrserver.com/v1/create-qr-code/?data=$encodedData&size=${qrSize}x${qrSize}&bgcolor=$bgColor&color=$color"; return "https://api.qrserver.com/v1/create-qr-code/?data=$encodedData&size=${qrSize}x$qrSize&bgcolor=$bgColor&color=$color";
} }
Future<void> saveImage(Uint8List imageBytes) async { Future<void> saveImage(Uint8List imageBytes) async {
@ -206,17 +204,10 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
backgroundColor: MihColors.secondary(), backgroundColor: MihColors.secondary(),
onChange: () {}, onChange: () {},
) )
: FutureBuilder( : MihCircleAvatar(
future: futureImageUrl,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState ==
ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "" ||
asyncSnapshot.requireData.isNotEmpty) {
return MihCircleAvatar(
imageFile: CachedNetworkImageProvider( imageFile: CachedNetworkImageProvider(
asyncSnapshot.requireData), MihFileApi.getMinioFileUrlV2(business.logo_path),
),
width: profilePictureWidth, width: profilePictureWidth,
expandable: true, expandable: true,
editable: false, editable: false,
@ -225,22 +216,6 @@ class _MihBusinessQrCodeState extends State<MihBusinessQrCode> {
frameColor: MihColors.primary(), frameColor: MihColors.primary(),
backgroundColor: MihColors.secondary(), backgroundColor: MihColors.secondary(),
onChange: () {}, onChange: () {},
);
} else {
return Icon(
MihIcons.mihIDontKnow,
size: profilePictureWidth,
color: MihColors.primary(),
);
}
} else {
return Icon(
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.primary(),
);
}
},
), ),
FittedBox( FittedBox(
child: Text( child: Text(

View file

@ -86,12 +86,9 @@ class _MihEditPersonalProfileWindowState
); );
if (responseCode == 200) { if (responseCode == 200) {
setState(() { setState(() {
setProfileVariables(mzansiProfileProvider);
newSelectedProPic = null; newSelectedProPic = null;
}); });
// if (originalProfileTypeIsBusiness == false && businessUser == true) { await mzansiProfileProvider.syncWithMihServerData();
// stayOnPersonalSide = false;
// }
String message = "Your information has been updated successfully!"; String message = "Your information has been updated successfully!";
successPopUp( successPopUp(
mzansiProfileProvider, mzansiProfileProvider,

View file

@ -174,12 +174,14 @@ class _MihPersonalProfileState extends State<MihPersonalProfile> {
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
MihButton( mzansiProfileProvider.user!.username != ""
? MihButton(
onPressed: () { onPressed: () {
addProfileLinksWindow(); addProfileLinksWindow();
}, },
buttonColor: MihColors.green(), buttonColor: MihColors.green(),
width: mzansiProfileProvider.personalLinks.isNotEmpty width:
mzansiProfileProvider.personalLinks.isNotEmpty
? 50 ? 50
: null, : null,
height: 50, height: 50,
@ -191,7 +193,8 @@ class _MihPersonalProfileState extends State<MihPersonalProfile> {
Icons.add, Icons.add,
color: MihColors.primary(), color: MihColors.primary(),
), ),
if (mzansiProfileProvider.personalLinks.isEmpty) if (mzansiProfileProvider
.personalLinks.isEmpty)
Text( Text(
"Add Links", "Add Links",
style: TextStyle( style: TextStyle(
@ -202,6 +205,35 @@ class _MihPersonalProfileState extends State<MihPersonalProfile> {
), ),
], ],
), ),
)
: MihButton(
onPressed: () {
editProfileWindow();
},
buttonColor: MihColors.green(),
width: null,
height: 50,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
Icons.edit,
color: MihColors.primary(),
),
const SizedBox(
width: 10,
),
Text(
"Add Profile",
style: TextStyle(
color: MihColors.primary(),
fontSize: 15,
fontWeight: FontWeight.bold,
),
),
],
),
), ),
const SizedBox(width: 8.0), const SizedBox(width: 8.0),
if (mzansiProfileProvider.personalLinks.isNotEmpty) if (mzansiProfileProvider.personalLinks.isNotEmpty)

View file

@ -75,16 +75,12 @@ class _MihPersonalProfileViewState extends State<MihPersonalProfileView> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
FutureBuilder( MihCircleAvatar(
future: futureImageUrl,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState ==
ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "") {
return MihCircleAvatar(
imageFile: CachedNetworkImageProvider( imageFile: CachedNetworkImageProvider(
asyncSnapshot.requireData), MihFileApi.getMinioFileUrlV2(
directoryProvider.selectedUser!.pro_pic_path,
),
),
width: profilePictureWidth, width: profilePictureWidth,
expandable: true, expandable: true,
editable: false, editable: false,
@ -93,22 +89,7 @@ class _MihPersonalProfileViewState extends State<MihPersonalProfileView> {
frameColor: MihColors.secondary(), frameColor: MihColors.secondary(),
backgroundColor: MihColors.primary(), backgroundColor: MihColors.primary(),
onChange: () {}, onChange: () {},
); ),
} else {
return Icon(
MihIcons.mihIDontKnow,
size: profilePictureWidth,
color: MihColors.secondary(),
);
}
} else {
return Icon(
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.secondary(),
);
}
}),
FittedBox( FittedBox(
child: Text( child: Text(
directoryProvider.selectedUser!.username.isNotEmpty directoryProvider.selectedUser!.username.isNotEmpty

View file

@ -206,17 +206,10 @@ class _MihPersonalQrCodeState extends State<MihPersonalQrCode> {
backgroundColor: MihColors.secondary(), backgroundColor: MihColors.secondary(),
onChange: () {}, onChange: () {},
) )
: FutureBuilder( : MihCircleAvatar(
future: futureImageUrl,
builder: (context, asyncSnapshot) {
if (asyncSnapshot.connectionState ==
ConnectionState.done &&
asyncSnapshot.hasData) {
if (asyncSnapshot.requireData != "" ||
asyncSnapshot.requireData.isNotEmpty) {
return MihCircleAvatar(
imageFile: CachedNetworkImageProvider( imageFile: CachedNetworkImageProvider(
asyncSnapshot.requireData), MihFileApi.getMinioFileUrlV2(user.pro_pic_path),
),
width: profilePictureWidth, width: profilePictureWidth,
expandable: true, expandable: true,
editable: false, editable: false,
@ -225,22 +218,6 @@ class _MihPersonalQrCodeState extends State<MihPersonalQrCode> {
frameColor: MihColors.primary(), frameColor: MihColors.primary(),
backgroundColor: MihColors.secondary(), backgroundColor: MihColors.secondary(),
onChange: () {}, onChange: () {},
);
} else {
return Icon(
MihIcons.mihIDontKnow,
size: profilePictureWidth,
color: MihColors.primary(),
);
}
} else {
return Icon(
MihIcons.mihRing,
size: profilePictureWidth,
color: MihColors.primary(),
);
}
},
), ),
FittedBox( FittedBox(
child: Text( child: Text(

View file

@ -29,8 +29,15 @@ class AboutMihProvider extends ChangeNotifier {
return success; return success;
} }
Future<void> clearAboutMihCacheAndProvider() async {
await _hiveData.clearAboutMIHCache();
reset();
}
void reset() { void reset() {
toolIndex = 0; toolIndex = 0;
userCount = null;
businessCount = null;
notifyListeners(); notifyListeners();
} }

View file

@ -9,7 +9,6 @@ class MihMineSweeperProvider extends ChangeNotifier {
int totalMines; int totalMines;
List<MinesweeperPlayerScore>? leaderboard; List<MinesweeperPlayerScore>? leaderboard;
List<MinesweeperPlayerScore>? myScoreboard; List<MinesweeperPlayerScore>? myScoreboard;
List<Future<String>> leaderboardUserPicturesUrl = [];
MihMineSweeperProvider({ MihMineSweeperProvider({
this.difficulty = "Easy", this.difficulty = "Easy",
@ -72,10 +71,4 @@ class MihMineSweeperProvider extends ChangeNotifier {
} }
notifyListeners(); notifyListeners();
} }
void setLeaderboardUserPictures(
{required List<Future<String>> leaderboardUserPicturesUrl}) {
this.leaderboardUserPicturesUrl = leaderboardUserPicturesUrl;
notifyListeners();
}
} }

View file

@ -13,12 +13,9 @@ class MzansiDirectoryProvider extends ChangeNotifier {
bool personalSearch; bool personalSearch;
List<BookmarkedBusiness> bookmarkedBusinesses = []; List<BookmarkedBusiness> bookmarkedBusinesses = [];
List<Business>? favouriteBusinessesList; List<Business>? favouriteBusinessesList;
Map<String, Future<String>>? favBusImagesUrl;
List<Business> searchedBusinesses = []; List<Business> searchedBusinesses = [];
Map<String, Future<String>>? busSearchImagesUrl;
Business? selectedBusiness; Business? selectedBusiness;
List<AppUser> searchedUsers = []; List<AppUser> searchedUsers = [];
Map<String, Future<String>>? userSearchImagesUrl;
AppUser? selectedUser; AppUser? selectedUser;
String searchTerm; String searchTerm;
String businessTypeFilter; String businessTypeFilter;
@ -88,19 +85,15 @@ class MzansiDirectoryProvider extends ChangeNotifier {
void setFavouriteBusinesses({ void setFavouriteBusinesses({
required List<Business> businesses, required List<Business> businesses,
required Map<String, Future<String>> businessesImagesUrl,
}) { }) {
favouriteBusinessesList = businesses; favouriteBusinessesList = businesses;
favBusImagesUrl = businessesImagesUrl;
notifyListeners(); notifyListeners();
} }
void setSearchedBusinesses({ void setSearchedBusinesses({
required List<Business> searchedBusinesses, required List<Business> searchedBusinesses,
required Map<String, Future<String>> businessesImagesUrl,
}) { }) {
this.searchedBusinesses = searchedBusinesses; this.searchedBusinesses = searchedBusinesses;
busSearchImagesUrl = businessesImagesUrl;
notifyListeners(); notifyListeners();
} }
@ -111,10 +104,8 @@ class MzansiDirectoryProvider extends ChangeNotifier {
void setSearchedUsers({ void setSearchedUsers({
required List<AppUser> searchedUsers, required List<AppUser> searchedUsers,
required Map<String, Future<String>> userImagesUrl,
}) { }) {
this.searchedUsers = searchedUsers; this.searchedUsers = searchedUsers;
this.userSearchImagesUrl = userImagesUrl;
notifyListeners(); notifyListeners();
} }

View file

@ -75,6 +75,7 @@ class MzansiProfileProvider extends ChangeNotifier {
} }
Future<bool> syncWithMihServerData() async { Future<bool> syncWithMihServerData() async {
await _hiveData.processModificationsQueue();
bool success = await _hiveData.syncProfileDataWithServer(); bool success = await _hiveData.syncProfileDataWithServer();
loadCachedProfileState(); loadCachedProfileState();
return success; return success;
@ -84,6 +85,24 @@ class MzansiProfileProvider extends ChangeNotifier {
refreshIndicatorKey.currentState?.show(); refreshIndicatorKey.currentState?.show();
} }
bool isLocalModificationsPending(){
return _hiveData.isModificationsNotEmpty();
}
Future<bool> addUserConsent(UserConsent newConsent) async {
bool success = await _hiveData.addUserConsentLocally(newConsent);
await _hiveData.queuAddConsentModification(newConsent);
await _hiveData.processModificationsQueue();
await _hiveData.syncProfileDataWithServer();
loadCachedProfileState();
return success;
}
Future<void> clearProfileCacheAndProvider() async {
await _hiveData.clearProfileCache();
reset();
}
void reset() { void reset() {
personalHome = true; personalHome = true;
personalIndex = 0; personalIndex = 0;
@ -98,6 +117,10 @@ class MzansiProfileProvider extends ChangeNotifier {
businessUserSignatureUrl = null; businessUserSignatureUrl = null;
businessUserSignature = null; businessUserSignature = null;
userConsent = null; userConsent = null;
employeeList = null;
userSearchResults = [];
personalLinks = [];
businessLinks = [];
notifyListeners(); notifyListeners();
} }

View file

@ -64,10 +64,16 @@ class MzansiWalletProvider extends ChangeNotifier {
loadCachedWallet(); loadCachedWallet();
} }
Future<void> clearWalletCacheAndProvider() async {
await _hiveData.clearWalletCache();
reset();
}
void reset() { void reset() {
toolIndex = 0; toolIndex = 0;
loyaltyCards = []; loyaltyCards = [];
favouriteCards = []; favouriteCards = [];
notifyListeners();
} }
void setToolIndex(int index) { void setToolIndex(int index) {

View file

@ -4,11 +4,85 @@ import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart'; import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_user_services.dart';
import 'package:provider/provider.dart';
import 'package:supertokens_flutter/http.dart' as http; import 'package:supertokens_flutter/http.dart' as http;
import 'package:supertokens_flutter/supertokens.dart';
class MihAuthenticationServices { class MihAuthenticationServices {
final baseAPI = AppEnviroment.baseApiUrl; final baseAPI = AppEnviroment.baseApiUrl;
bool validEmail(String email) {
var regex = RegExp(r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$');
return regex.hasMatch(email);
}
Future<void> signUserUp(
String email,
String password,
String confirmPassword,
BuildContext context,
) async {
context.read<MzansiProfileProvider>().reset();
if (!validEmail(email)) {
MihAlertServices().invalidEmailAlert(context);
} else if (password != confirmPassword) {
MihAlertServices().passwordMatchAlert(context);
} else {
showDialog(
context: context,
builder: (context) {
return const Mihloadingcircle();
},
);
try {
Uri uri =
Uri.parse("$baseAPI/auth/emailpassword/email/exists?email=$email");
var response = await http.get(uri);
if (response.statusCode == 200) {
var userExists = jsonDecode(response.body);
if (userExists["exists"]) {
context.pop();
MihAlertServices().emailExistsAlert(context);
} else {
var response2 = await http.post(
Uri.parse("$baseAPI/auth/signup"),
body:
'{"formFields": [{"id": "email","value": "$email"}, {"id": "password","value": "$password"}]}',
headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
},
);
if (response2.statusCode == 200) {
var userCreated = jsonDecode(response2.body);
if (userCreated["status"] == "OK") {
String uid = await SuperTokens.getUserId();
await MihUserServices().createUser(
email,
uid,
context,
);
context.pop();
} else if (userCreated["status"] == "FIELD_ERROR") {
context.pop();
MihAlertServices().passwordRequirementAlert(context);
} else {
context.pop();
MihAlertServices().internetConnectionAlert(context);
}
}
}
}
} on Exception catch (error) {
Navigator.of(context).pop();
signUpError(error, context);
}
}
}
Future<bool> signUserIn( Future<bool> signUserIn(
String email, String email,
String password, String password,
@ -104,74 +178,28 @@ class MihAuthenticationServices {
); );
} }
void signUpError(BuildContext context) { void signUpError(Exception error, BuildContext context) {
showDialog( MihAlertServices().errorAdvancedAlert(
context: context, "Sign Up Error",
barrierDismissible: false, "An error occurred while signing up: $error Please try again later.",
builder: (context) { [
return MihPackageWindow(
fullscreen: false,
windowTitle: null,
onWindowTapClose: null,
backgroundColor: MihColors.red(),
windowBody: Column(
children: [
Icon(
Icons.warning_amber_rounded,
size: 100,
color: MihColors.primary(),
),
Center(
child: Text(
"Email Already Exists",
textAlign: TextAlign.center,
style: TextStyle(
color: MihColors.primary(),
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
),
const SizedBox(height: 15),
Text(
"Here are some things to keep in mind:",
style: TextStyle(
color: MihColors.red(),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
Text(
"1) Are you sure you're using the correct email address associated with your account?\n2) Is your caps lock key on? Passwords are case-sensitive.\n3) If you've forgotten your password, no worries! Click on \"Forgot Password?\" to reset it.",
textAlign: TextAlign.left,
style: TextStyle(
color: MihColors.secondary(),
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 15),
MihButton( MihButton(
onPressed: () { onPressed: () {
context.pop(); Navigator.of(context).pop();
}, },
buttonColor: MihColors.secondary(), buttonColor: MihColors.secondary(),
width: 300, width: 200,
elevation: 10,
child: Text( child: Text(
"Dismiss", "Dismiss",
style: TextStyle( style: TextStyle(
color: MihColors.primary(), color: MihColors.primary(),
fontSize: 20, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
), ),
), ),
], ],
), context,
);
},
); );
} }
} }

View file

@ -1,5 +1,3 @@
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.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart'; import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart'; import 'package:mzansi_innovation_hub/mih_services/mih_business_details_services.dart';
@ -12,7 +10,7 @@ class MihDataHelperServices {
Future<void> getUserData(MzansiProfileProvider profileProvider) async { Future<void> getUserData(MzansiProfileProvider profileProvider) async {
String url; String url;
await MihUserServices().getMyUserDetails(profileProvider); await MihUserServices().getMyUserDetails(profileProvider);
url = await MihFileApi.getMinioFileUrl( url = MihFileApi.getMinioFileUrlV2(
profileProvider.user!.pro_pic_path, profileProvider.user!.pro_pic_path,
); );
profileProvider.setUserProfilePicUrl(url); profileProvider.setUserProfilePicUrl(url);
@ -29,12 +27,12 @@ class MihDataHelperServices {
Business? responseBusiness = await MihBusinessDetailsServices() Business? responseBusiness = await MihBusinessDetailsServices()
.getBusinessDetailsByUser(profileProvider); .getBusinessDetailsByUser(profileProvider);
if (responseBusiness != null) { if (responseBusiness != null) {
logoUrl = await MihFileApi.getMinioFileUrl( logoUrl = MihFileApi.getMinioFileUrlV2(
profileProvider.business!.logo_path, profileProvider.business!.logo_path,
); );
profileProvider.setBusinessProfilePicUrl(logoUrl); profileProvider.setBusinessProfilePicUrl(logoUrl);
await MihMyBusinessUserServices().getBusinessUser(profileProvider); await MihMyBusinessUserServices().getBusinessUser(profileProvider);
signatureUrl = await MihFileApi.getMinioFileUrl( signatureUrl = MihFileApi.getMinioFileUrlV2(
profileProvider.businessUser!.sig_path, profileProvider.businessUser!.sig_path,
); );
profileProvider.setBusinessUserSignatureUrl(signatureUrl); profileProvider.setBusinessUserSignatureUrl(signatureUrl);

View file

@ -54,6 +54,23 @@ class MihUserConsentServices {
return response.statusCode; return response.statusCode;
} }
Future<int?> insertUserConsentStatusV2(
UserConsent userConsent,
) async {
try {
final response = await http
.post(
Uri.parse("${AppEnviroment.baseApiUrl}/user-consent/insert/"),
headers: {"Content-Type": "application/json"},
body: jsonEncode(userConsent.toJson()),
)
.timeout(const Duration(seconds: 5));
return response.statusCode;
} catch (error) {
return null;
}
}
Future<int> updateUserConsentStatus( Future<int> updateUserConsentStatus(
String latestPrivacyPolicyDate, String latestPrivacyPolicyDate,
String latestTermOfServiceDate, String latestTermOfServiceDate,

View file

@ -1137,29 +1137,29 @@ packages:
source: hosted source: hosted
version: "6.1.0" version: "6.1.0"
local_auth: local_auth:
dependency: "direct main" dependency: transitive
description: description:
name: local_auth name: local_auth
sha256: "434d854cf478f17f12ab29a76a02b3067f86a63a6d6c4eb8fbfdcfe4879c1b7b" sha256: ae6f382f638108c6becd134318d7c3f0a93875383a54010f61d7c97ac05d5137
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "3.0.1"
local_auth_android: local_auth_android:
dependency: transitive dependency: transitive
description: description:
name: local_auth_android name: local_auth_android
sha256: a0bdfcc0607050a26ef5b31d6b4b254581c3d3ce3c1816ab4d4f4a9173e84467 sha256: fdb936d59ab945c7af297defd67bd1ed87b11b6db1bc16d01e94677a8f1c38ec
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.56" version: "2.0.9"
local_auth_darwin: local_auth_darwin:
dependency: transitive dependency: transitive
description: description:
name: local_auth_darwin name: local_auth_darwin
sha256: "699873970067a40ef2f2c09b4c72eb1cfef64224ef041b3df9fdc5c4c1f91f49" sha256: a8c3d4e17454111f7fd31ff72a31222359f6059f7fe956c2dcfe0f88f49826d4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.6.1" version: "2.0.3"
local_auth_platform_interface: local_auth_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -1172,10 +1172,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: local_auth_windows name: local_auth_windows
sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5 sha256: be12c5b8ba5e64896983123655c5f67d2484ecfcc95e367952ad6e3bff94cb16
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.11" version: "2.0.1"
logging: logging:
dependency: transitive dependency: transitive
description: description:
@ -1236,10 +1236,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: mih_package_toolkit name: mih_package_toolkit
sha256: "3d0dec0ae9471a37b8c6822419633643721b6b463f2b9b862233feefcec6e8a6" sha256: d648dd37dc69c01c552f45e98d69bb2b324cff382e8e36537a96ed5a812d03f8
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.0.6" version: "0.1.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:

View file

@ -5,24 +5,20 @@ version: 1.4.0+135
environment: environment:
sdk: ">=3.5.3 <4.0.0" sdk: ">=3.5.3 <4.0.0"
# flutter: ">=1.17.0"
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
flutter_web_plugins: flutter_web_plugins:
sdk: flutter sdk: flutter
mih_package_toolkit: ^0.0.6 mih_package_toolkit: ^0.1.0
cupertino_icons: ^1.0.8 cupertino_icons: ^1.0.8
font_awesome_flutter: ^11.0.0 font_awesome_flutter: ^11.0.0
# firebase_core: ^4.4.0
# firebase_core_desktop: ^1.0.2
syncfusion_flutter_core: ^33.2.15 syncfusion_flutter_core: ^33.2.15
syncfusion_flutter_pdfviewer: ^33.2.15 syncfusion_flutter_pdfviewer: ^33.2.15
universal_html: ^2.2.4 universal_html: ^2.2.4
file_picker: ^12.0.0-beta.7 file_picker: ^12.0.0-beta.7
supertokens_flutter: ^0.6.3 supertokens_flutter: ^0.6.3
http: ^1.2.1 http: ^1.2.1
# args: ^2.7.0
intl: ^0.20.2 intl: ^0.20.2
flutter_native_splash: ^2.4.6 flutter_native_splash: ^2.4.6
printing: ^5.14.2 printing: ^5.14.2
@ -34,7 +30,6 @@ dependencies:
barcode_widget: ^2.0.4 #Generate Barcodes barcode_widget: ^2.0.4 #Generate Barcodes
url_launcher: ^6.3.1 url_launcher: ^6.3.1
fl_downloader: ^2.0.2 fl_downloader: ^2.0.2
local_auth: ^2.3.0
math_expressions: ^3.1.0 math_expressions: ^3.1.0
ollama_dart: ^2.3.0 ollama_dart: ^2.3.0
flutter_chat_ui: ^2.11.1 flutter_chat_ui: ^2.11.1
@ -43,7 +38,6 @@ dependencies:
flutter_tts: ^4.2.3 flutter_tts: ^4.2.3
flutter_speed_dial: ^7.0.0 flutter_speed_dial: ^7.0.0
share_plus: ^13.2.0 share_plus: ^13.2.0
#app_settings: ^6.1.1
pwa_install: ^0.0.6 pwa_install: ^0.0.6
google_mobile_ads: ^8.0.0 google_mobile_ads: ^8.0.0
gma_mediation_meta: ^1.5.2 gma_mediation_meta: ^1.5.2