Complete Offline Wallet Display & Edit

This commit is contained in:
yaso 2026-06-30 16:21:47 +02:00
parent 6ad1ea613c
commit 04f034971f
21 changed files with 973 additions and 507 deletions

View file

@ -11,6 +11,7 @@ import 'package:mzansi_innovation_hub/main.dart';
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/appointment.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';
@ -45,7 +46,12 @@ void main() async {
// Mzansi Wallet Data
await Hive.openBox<MIHLoyaltyCard>('loyalty_card_box');
await Hive.openBox<MIHLoyaltyCard>('fav_loyalty_card_box');
await Hive.openBox<Map>('wallet_modifications_queue');
// About MIH Data
await Hive.openBox<int>('about_mih_box');
// Mih Calendar Data
await Hive.openBox<Appointment>('personal_calendar_box');
await Hive.openBox<Appointment>('business_calendar_box');
// await Firebase.initializeApp(
// // options: DefaultFirebaseOptions.currentPlatform,

View file

@ -1,6 +1,7 @@
// hive_adapters.dart
import 'package:hive_ce/hive_ce.dart';
import 'package:mzansi_innovation_hub/mih_objects/app_user.dart';
import 'package:mzansi_innovation_hub/mih_objects/appointment.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';
@ -16,5 +17,6 @@ import 'package:mzansi_innovation_hub/mih_objects/user_consent.dart';
AdapterSpec<ProfileLink>(),
AdapterSpec<BusinessEmployee>(),
AdapterSpec<MIHLoyaltyCard>(),
AdapterSpec<Appointment>(),
])
part 'hive_adapters.g.dart';

View file

@ -357,13 +357,14 @@ class MIHLoyaltyCardAdapter extends TypeAdapter<MIHLoyaltyCard> {
favourite: fields[4] as String,
priority_index: (fields[5] as num).toInt(),
nickname: fields[6] as String,
offline_id: fields[7] as String?,
);
}
@override
void write(BinaryWriter writer, MIHLoyaltyCard obj) {
writer
..writeByte(7)
..writeByte(8)
..writeByte(0)
..write(obj.idloyalty_cards)
..writeByte(1)
@ -377,7 +378,9 @@ class MIHLoyaltyCardAdapter extends TypeAdapter<MIHLoyaltyCard> {
..writeByte(5)
..write(obj.priority_index)
..writeByte(6)
..write(obj.nickname);
..write(obj.nickname)
..writeByte(7)
..write(obj.offline_id);
}
@override
@ -390,3 +393,52 @@ class MIHLoyaltyCardAdapter extends TypeAdapter<MIHLoyaltyCard> {
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class AppointmentAdapter extends TypeAdapter<Appointment> {
@override
final typeId = 7;
@override
Appointment read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return Appointment(
idappointments: (fields[0] as num).toInt(),
app_id: fields[1] as String,
business_id: fields[2] as String,
date_time: fields[3] as String,
title: fields[4] as String,
description: fields[5] as String,
);
}
@override
void write(BinaryWriter writer, Appointment obj) {
writer
..writeByte(6)
..writeByte(0)
..write(obj.idappointments)
..writeByte(1)
..write(obj.app_id)
..writeByte(2)
..write(obj.business_id)
..writeByte(3)
..write(obj.date_time)
..writeByte(4)
..write(obj.title)
..writeByte(5)
..write(obj.description);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is AppointmentAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View file

@ -1,7 +1,7 @@
# Generated by Hive CE
# Manual modifications may be necessary for certain migrations
# Check in to version control
nextTypeId: 7
nextTypeId: 8
types:
AppUser:
typeId: 0
@ -127,7 +127,7 @@ types:
index: 7
MIHLoyaltyCard:
typeId: 6
nextIndex: 7
nextIndex: 8
fields:
idloyalty_cards:
index: 0
@ -143,3 +143,21 @@ types:
index: 5
nickname:
index: 6
offline_id:
index: 7
Appointment:
typeId: 7
nextIndex: 6
fields:
idappointments:
index: 0
app_id:
index: 1
business_id:
index: 2
date_time:
index: 3
title:
index: 4
description:
index: 5

View file

@ -0,0 +1,33 @@
import 'package:hive_ce_flutter/hive_ce_flutter.dart';
import 'package:mzansi_innovation_hub/mih_objects/appointment.dart';
class MihCalendarHiveData {
final Box<Appointment> _personalAppointmentBox =
Hive.box<Appointment>('personal_calendar_box');
final Box<Appointment> _businessAppointmentBox =
Hive.box<Appointment>('business_calendar_box');
List<Appointment> getCachedPersonalAppointments() {
final appointments = _personalAppointmentBox.values.toList();
appointments.sort((a, b) {
final dateA = DateTime.parse(a.date_time);
final dateB = DateTime.parse(b.date_time);
return dateB.compareTo(dateA);
});
return appointments;
}
List<Appointment> getCachedBusinessAppointments() {
final appointments = _businessAppointmentBox.values.toList();
appointments.sort((a, b) {
final dateA = DateTime.parse(a.date_time);
final dateB = DateTime.parse(b.date_time);
return dateB.compareTo(dateA);
});
return appointments;
}
Future<bool> syncCalendarDataWithServer() async {
return false;
}
}

View file

@ -3,12 +3,15 @@ import 'package:ken_logger/ken_logger.dart';
import 'package:mzansi_innovation_hub/mih_objects/loyalty_card.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_wallet_services.dart';
import 'package:uuid/uuid.dart';
class MzansiWalletHiveData {
final Box<MIHLoyaltyCard> _loyaltyCardBox =
Hive.box<MIHLoyaltyCard>('loyalty_card_box');
final Box<MIHLoyaltyCard> _favLoyaltyCardBox =
Hive.box<MIHLoyaltyCard>('fav_loyalty_card_box');
final Box<Map> _modificationsQueue =
Hive.box<Map>('wallet_modifications_queue');
// Get Offline Data
List<MIHLoyaltyCard> getCachedLoyaltyCards() {
@ -19,10 +22,116 @@ class MzansiWalletHiveData {
List<MIHLoyaltyCard> getCachedFavLoyaltyCards() {
final cards = _favLoyaltyCardBox.values.toList();
cards.sort((a, b) => a.shop_name.compareTo(b.shop_name));
cards.sort((a, b) => a.priority_index.compareTo(b.priority_index));
return cards;
}
// Set Offline Data
Future<void> addLoyaltyCardLocally(MIHLoyaltyCard newCard) async {
await _loyaltyCardBox.put(newCard.offline_id, newCard);
if (newCard.favourite == "Yes") {
await _favLoyaltyCardBox.put(newCard.offline_id, newCard);
}
KenLogger.success("New Card Saved Locally.");
}
Future<void> deleteLoyaltyCardLocally(MIHLoyaltyCard deleteCard) async {
dynamic mainTargetKey;
dynamic favTargetKey;
for (var key in _loyaltyCardBox.keys) {
final card = _loyaltyCardBox.get(key);
if (card != null) {
if (deleteCard.idloyalty_cards != 0 &&
card.idloyalty_cards == deleteCard.idloyalty_cards) {
mainTargetKey = key;
break;
} else if (deleteCard.idloyalty_cards == 0 &&
card.offline_id == deleteCard.offline_id) {
mainTargetKey = key;
break;
}
}
}
for (var key in _favLoyaltyCardBox.keys) {
final card = _favLoyaltyCardBox.get(key);
if (card != null) {
if (deleteCard.idloyalty_cards != 0 &&
card.idloyalty_cards == deleteCard.idloyalty_cards) {
favTargetKey = key;
break;
} else if (deleteCard.idloyalty_cards == 0 &&
card.offline_id == deleteCard.offline_id) {
favTargetKey = key;
break;
}
}
}
if (mainTargetKey != null) {
await _loyaltyCardBox.delete(mainTargetKey);
KenLogger.success("Card Deleted Locally.");
}
if (favTargetKey != null) {
await _favLoyaltyCardBox.delete(favTargetKey);
KenLogger.success("Fav Card Deleted Locally.");
}
}
Future<void> updateLoyaltyCardLocally(MIHLoyaltyCard updatedCard) async {
dynamic mainTargetKey;
dynamic favTargetKey;
for (var key in _loyaltyCardBox.keys) {
final card = _loyaltyCardBox.get(key);
if (card != null) {
if (updatedCard.idloyalty_cards != 0 &&
card.idloyalty_cards == updatedCard.idloyalty_cards) {
mainTargetKey = key;
break;
} else if (updatedCard.idloyalty_cards == 0 &&
card.offline_id == updatedCard.offline_id) {
mainTargetKey = key;
break;
}
}
}
for (var key in _favLoyaltyCardBox.keys) {
final card = _favLoyaltyCardBox.get(key);
if (card != null) {
if (updatedCard.idloyalty_cards != 0 &&
card.idloyalty_cards == updatedCard.idloyalty_cards) {
favTargetKey = key;
break;
} else if (updatedCard.idloyalty_cards == 0 &&
card.offline_id == updatedCard.offline_id) {
favTargetKey = key;
break;
}
}
}
if (mainTargetKey != null) {
await _loyaltyCardBox.put(mainTargetKey, updatedCard);
KenLogger.success("Card Udpdated Locally.");
}
if (favTargetKey != null) {
if (updatedCard.favourite == "Yes") {
await _favLoyaltyCardBox.put(favTargetKey, updatedCard);
KenLogger.success("Fav Card Updated Locally.");
} else {
await _favLoyaltyCardBox.delete(favTargetKey);
KenLogger.success("Fav Card Removed Locally.");
}
} else {
if (updatedCard.offline_id == null) {
final String uniqueKey = const Uuid().v4();
await _favLoyaltyCardBox.put(uniqueKey, updatedCard);
KenLogger.success("Fav Card Added Locally.");
} else {
await _favLoyaltyCardBox.put(updatedCard.offline_id, updatedCard);
KenLogger.success("Fav Card Added Locally.");
}
}
}
// Cache data for offline use
Future<void> cacheFavLoyaltyCardsData(
List<MIHLoyaltyCard> remoteLoyaltyCards) async {
@ -51,9 +160,122 @@ class MzansiWalletHiveData {
cacheFavLoyaltyCardsData(remoteFavLoyaltyCards);
return true;
} catch (error) {
KenLogger.warning("MIH App Operating in Offline Mode. Sync Paused");
KenLogger.warning("MIH App Operating in Offline Mode. Sync Paused.");
return false;
// KenLogger.warning("App operating offline mode. Sync paused: $error");
}
}
// Modicfications processing
Future<void> queueAddModification(MIHLoyaltyCard newCardData) async {
await _modificationsQueue.add({
'action': 'ADD',
'payload': newCardData,
});
KenLogger.warning("Add Card Queued For Online Sync");
}
Future<void> queueDeleteModification(MIHLoyaltyCard deleteCardData) async {
await _modificationsQueue.add({
'action': 'DELETE',
'payload': deleteCardData,
});
KenLogger.warning("Delete Card Queued For Online Sync");
}
Future<void> queueUpdateModification(MIHLoyaltyCard updatedCardData) async {
await _modificationsQueue.add({
'action': 'UPDATE',
'payload': updatedCardData,
});
KenLogger.warning("Update Card Queued For Online Sync");
}
Future<bool> processModificationsQueue(
MzansiProfileProvider profileProvider) 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 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') {
dynamic deleteCardTaskKey;
for (var entry in _modificationsQueue.toMap().entries) {
if (entry.value['action'] == 'DELETE' &&
entry.value['payload'].offline_id == taskCard.offline_id) {
deleteCardTaskKey = entry.key;
break;
}
}
if (deleteCardTaskKey != null) {
await _modificationsQueue.delete(taskKey); // Remove 'ADD'
await _modificationsQueue
.delete(deleteCardTaskKey); // Remove 'DELETE'
KenLogger.success(
"Offline add & delete cancelled out. Queue cleaned.");
continue;
}
final responseCode = await MIHMzansiWalletApis.addLoyaltyCardAPICallV2(
profileProvider.user!.app_id,
taskCard.shop_name,
taskCard.card_number,
taskCard.favourite,
taskCard.priority_index,
taskCard.nickname,
);
if (responseCode != null && responseCode == 201) {
await _modificationsQueue.delete(taskKey);
KenLogger.success("Add New Local Card to MIH Server");
} else {
KenLogger.warning("MIH App Operating in Offline Mode. Sync Paused");
return false;
}
}
if (action == 'DELETE') {
final responseCode =
await MIHMzansiWalletApis.deleteLoyaltyCardAPICallV2(
taskCard.idloyalty_cards,
);
if (responseCode != null && responseCode == 200) {
await _modificationsQueue.delete(taskKey);
KenLogger.success("Delete Local Card from MIH Server");
} else {
KenLogger.warning("MIH App Operating in Offline Mode. Sync Paused");
return false;
}
}
if (action == 'UPDATE') {
final responseCode =
await MIHMzansiWalletApis.updateLoyaltyCardAPICallV2(
taskCard.idloyalty_cards,
taskCard.favourite,
taskCard.priority_index,
taskCard.nickname,
taskCard.card_number,
);
if (responseCode != null && responseCode == 200) {
await _modificationsQueue.delete(taskKey);
KenLogger.success("Update Local Card from MIH Server");
} else {
KenLogger.warning("MIH App Operating in Offline Mode. Sync Paused");
return false;
}
}
}
return true;
}
bool isModificationNotEmpty() {
return _modificationsQueue.values.toList().isNotEmpty;
}
}

View file

@ -6,6 +6,7 @@ class MIHLoyaltyCard {
final String favourite;
final int priority_index;
final String nickname;
final String? offline_id;
const MIHLoyaltyCard({
required this.idloyalty_cards,
@ -15,6 +16,7 @@ class MIHLoyaltyCard {
required this.favourite,
required this.priority_index,
required this.nickname,
this.offline_id,
});
factory MIHLoyaltyCard.fromJson(Map<String, dynamic> json) {

View file

@ -24,8 +24,6 @@ class _MzansiAiState extends State<MzansiAi> {
mzansiProfileProvider.loadCachedProfileState();
if (mzansiProfileProvider.user == null) {
await mzansiProfileProvider.syncWithMihServerData();
} else {
await mzansiProfileProvider.syncWithMihServerData();
}
}

View file

@ -11,7 +11,6 @@ import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/components/mih_
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_wallet_provider.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_wallet_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:mzansi_innovation_hub/mih_objects/loyalty_card.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/components/mih_card_display.dart';
@ -130,29 +129,27 @@ class _BuildLoyaltyCardListState extends State<BuildLoyaltyCardList> {
child: MihButton(
onPressed: () async {
if (_formKey.currentState!.validate()) {
int statusCode = await MIHMzansiWalletApis
.updateLoyaltyCardAPICall(
walletProvider,
mzansiProfileProvider.user!,
widget.cardList[index].idloyalty_cards,
widget.cardList[index].shop_name,
widget.cardList[index].favourite,
widget.cardList[index].priority_index,
_nicknameController.text,
_cardNumberController.text,
ctxt,
walletProvider.updateLocalLoyaltyCard(
mzansiProfileProvider,
MIHLoyaltyCard(
idloyalty_cards:
widget.cardList[index].idloyalty_cards,
app_id: widget.cardList[index].app_id,
shop_name: widget.cardList[index].shop_name,
card_number: _cardNumberController.text,
favourite: widget.cardList[index].favourite,
priority_index:
widget.cardList[index].priority_index,
nickname: _nicknameController.text,
),
);
context.pop();
context.pop();
MihAlertServices().successBasicAlert(
"Success!",
"You have successfully updated the loyalty card details.",
context,
);
if (statusCode == 200) {
context.pop();
context.pop();
MihAlertServices().successBasicAlert(
"Success!",
"You have successfully updated the loyalty card details.",
context,
);
} else {
MihAlertServices().internetConnectionAlert(context);
}
} else {
MihAlertServices().inputErrorAlert(context);
}
@ -183,24 +180,17 @@ class _BuildLoyaltyCardListState extends State<BuildLoyaltyCardList> {
MihAlertServices().deleteConfirmationAlert(
"This Card will be deleted permanently from your Mzansi Wallet. Are you certain you want to delete it?",
() async {
int statusCode = await MIHMzansiWalletApis.deleteLoyaltyCardAPICall(
walletProvider,
mzansiProfileProvider.user!,
widget.cardList[index].idloyalty_cards,
walletProvider.deleteLocalLoyaltyCard(
mzansiProfileProvider,
widget.cardList[index],
);
context.pop();
context.pop();
MihAlertServices().successBasicAlert(
"Success!",
"You have successfully deleted the loyalty card from your Mzansi Wallet.",
context,
);
if (statusCode == 200) {
context.pop();
context.pop();
MihAlertServices().successBasicAlert(
"Success!",
"You have successfully deleted the loyalty card from your Mzansi Wallet.",
context,
);
} else {
context.pop();
MihAlertServices().internetConnectionAlert(context);
}
},
context,
);
@ -231,34 +221,26 @@ class _BuildLoyaltyCardListState extends State<BuildLoyaltyCardList> {
),
MihButton(
onPressed: () async {
int statusCode = await MIHMzansiWalletApis.updateLoyaltyCardAPICall(
walletProvider,
mzansiProfileProvider.user!,
widget.cardList[index].idloyalty_cards,
widget.cardList[index].shop_name,
"Yes",
_noFavourites,
widget.cardList[index].nickname,
widget.cardList[index].card_number,
ctxt,
await walletProvider.updateLocalLoyaltyCard(
mzansiProfileProvider,
MIHLoyaltyCard(
idloyalty_cards: widget.cardList[index].idloyalty_cards,
app_id: widget.cardList[index].app_id,
shop_name: widget.cardList[index].shop_name,
card_number: widget.cardList[index].card_number,
favourite: "Yes",
priority_index: _noFavourites,
nickname: widget.cardList[index].nickname,
),
);
context.pop();
context.pop();
context.read<MzansiWalletProvider>().setToolIndex(1);
MihAlertServices().successBasicAlert(
"Success!",
"You have successfully added the loyalty card to your favourites.",
context,
);
if (statusCode == 200) {
context.pop();
context.pop();
await MIHMzansiWalletApis.getFavouriteLoyaltyCards(
walletProvider,
mzansiProfileProvider.user!.app_id,
context,
);
context.read<MzansiWalletProvider>().setToolIndex(1);
MihAlertServices().successBasicAlert(
"Success!",
"You have successfully added the loyalty card to your favourites.",
context,
);
} else {
MihAlertServices().internetConnectionAlert(context);
}
},
buttonColor: MihColors.green(),
width: 300,
@ -284,34 +266,26 @@ class _BuildLoyaltyCardListState extends State<BuildLoyaltyCardList> {
[
MihButton(
onPressed: () async {
int statusCode = await MIHMzansiWalletApis.updateLoyaltyCardAPICall(
walletProvider,
mzansiProfileProvider.user!,
widget.cardList[index].idloyalty_cards,
widget.cardList[index].shop_name,
"",
0,
widget.cardList[index].nickname,
widget.cardList[index].card_number,
ctxt,
await walletProvider.updateLocalLoyaltyCard(
mzansiProfileProvider,
MIHLoyaltyCard(
idloyalty_cards: widget.cardList[index].idloyalty_cards,
app_id: widget.cardList[index].app_id,
shop_name: widget.cardList[index].shop_name,
card_number: widget.cardList[index].card_number,
favourite: "",
priority_index: 0,
nickname: widget.cardList[index].nickname,
),
);
context.pop();
context.pop();
context.read<MzansiWalletProvider>().setToolIndex(0);
MihAlertServices().successBasicAlert(
"Success!",
"You have successfully removed the loyalty card to your favourites.",
context,
);
if (statusCode == 200) {
context.pop();
context.pop();
await MIHMzansiWalletApis.getFavouriteLoyaltyCards(
walletProvider,
mzansiProfileProvider.user!.app_id,
context,
);
context.read<MzansiWalletProvider>().setToolIndex(0);
MihAlertServices().successBasicAlert(
"Success!",
"You have successfully removed the loyalty card to your favourites.",
context,
);
} else {
MihAlertServices().internetConnectionAlert(context);
}
},
buttonColor: MihColors.red(),
width: 300,

View file

@ -3,13 +3,14 @@ import 'package:go_router/go_router.dart';
import 'package:ken_logger/ken_logger.dart';
import 'package:mih_package_toolkit/mih_package_toolkit.dart';
import 'package:mzansi_innovation_hub/main.dart';
import 'package:mzansi_innovation_hub/mih_objects/loyalty_card.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_profile_provider.dart';
import 'package:mzansi_innovation_hub/mih_providers/mzansi_wallet_provider.dart';
import 'package:mzansi_innovation_hub/mih_packages/mzansi_wallet/components/mih_card_display.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_alert_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_mzansi_wallet_services.dart';
import 'package:mzansi_innovation_hub/mih_services/mih_validation_services.dart';
import 'package:provider/provider.dart';
import 'package:uuid/uuid.dart';
class MihAddCardWindow extends StatefulWidget {
const MihAddCardWindow({
@ -58,6 +59,38 @@ class _MihAddCardWindowState extends State<MihAddCardWindow> {
}
}
void addLoyaltyCard(MzansiProfileProvider profileProvider,
MzansiWalletProvider walletProvider) async {
if (_formKey.currentState!.validate()) {
if (_shopController.text == "") {
MihAlertServices().inputErrorAlert(context);
} else {
final String uniqueKey = const Uuid().v4();
MIHLoyaltyCard newCard = MIHLoyaltyCard(
idloyalty_cards: 0,
app_id: profileProvider.user!.app_id,
shop_name: _shopController.text,
card_number: _cardNumberController.text,
favourite: "No",
priority_index: 0,
nickname: _nicknameController.text,
offline_id: uniqueKey,
);
await walletProvider.addLocalLoyaltyCard(profileProvider, newCard);
context.pop();
KenLogger.success("Card Added Successfully");
successPopUp(
"Successfully Added Card",
"The loyalty card has been added to your favourites.",
0,
);
}
} else {
MihAlertServices().inputErrorAlert(context);
}
}
@override
Widget build(BuildContext context) {
final double width = MediaQuery.sizeOf(context).width;
@ -224,38 +257,7 @@ class _MihAddCardWindowState extends State<MihAddCardWindow> {
Center(
child: MihButton(
onPressed: () async {
if (_formKey.currentState!.validate()) {
if (_shopController.text == "") {
MihAlertServices().inputErrorAlert(context);
} else {
int statusCode = await MIHMzansiWalletApis
.addLoyaltyCardAPICall(
walletProvider,
mzansiProfileProvider.user!,
mzansiProfileProvider.user!.app_id,
_shopController.text,
_cardNumberController.text,
"",
0,
_nicknameController.text,
context,
);
if (statusCode == 201) {
context.pop();
KenLogger.success("Card Added Successfully");
successPopUp(
"Successfully Added Card",
"The loyalty card has been added to your favourites.",
0,
);
} else {
MihAlertServices()
.internetConnectionAlert(context);
}
}
} else {
MihAlertServices().inputErrorAlert(context);
}
addLoyaltyCard(mzansiProfileProvider, walletProvider);
},
buttonColor: MihColors.green(),
width: 300,

View file

@ -28,7 +28,8 @@ class _MihWalletState extends State<MihWallet> {
if (mzansiProfileProvider.user == null) {
mzansiProfileProvider.syncWithMihServerData();
}
if (walletProvider.loyaltyCards.isEmpty) {
if (walletProvider.loyaltyCards.isEmpty ||
walletProvider.isLocalModificationsPending()) {
walletProvider.syncWithMihServerData(mzansiProfileProvider);
}
setState(() {

View file

@ -28,11 +28,42 @@ class MzansiWalletProvider extends ChangeNotifier {
Future<bool> syncWithMihServerData(
MzansiProfileProvider profileProvider) async {
await _hiveData.processModificationsQueue(profileProvider);
bool success = await _hiveData.syncWalletWithServer(profileProvider);
loadCachedWallet();
return success;
}
Future<void> addLocalLoyaltyCard(
MzansiProfileProvider profileProvider, MIHLoyaltyCard newCard) async {
await _hiveData.addLoyaltyCardLocally(newCard);
await _hiveData.queueAddModification(newCard);
await _hiveData.processModificationsQueue(profileProvider);
await _hiveData.syncWalletWithServer(profileProvider);
loadCachedWallet();
}
Future<void> deleteLocalLoyaltyCard(
MzansiProfileProvider profileProvider, MIHLoyaltyCard deleteCard) async {
await _hiveData.deleteLoyaltyCardLocally(deleteCard);
await _hiveData.queueDeleteModification(deleteCard);
loadCachedWallet();
_hiveData.processModificationsQueue(profileProvider);
}
bool isLocalModificationsPending() {
return _hiveData.isModificationNotEmpty();
}
Future<void> updateLocalLoyaltyCard(
MzansiProfileProvider profileProvider, MIHLoyaltyCard updatedCard) async {
await _hiveData.updateLoyaltyCardLocally(updatedCard);
await _hiveData.queueUpdateModification(updatedCard);
await _hiveData.processModificationsQueue(profileProvider);
await _hiveData.syncWalletWithServer(profileProvider);
loadCachedWallet();
}
void reset() {
toolIndex = 0;
loyaltyCards = [];

View file

@ -40,6 +40,25 @@ class MihMzansiCalendarApis {
}
}
static Future<int> getPersonalAppointmentsV2(
String app_id,
String date,
MihCalendarProvider mihCalendarProvider,
) async {
final response = await http.get(Uri.parse(
"${AppEnviroment.baseApiUrl}/appointments/personal/$app_id?date=$date"));
if (response.statusCode == 200) {
Iterable l = jsonDecode(response.body);
List<Appointment> personalAppointments =
List<Appointment>.from(l.map((model) => Appointment.fromJson(model)));
mihCalendarProvider.setPersonalAppointments(
appointments: personalAppointments);
return response.statusCode;
} else {
throw Exception('failed to fatch personal appointments');
}
}
/// This function is used to fetch a list of appointment for a personal user.
///
/// Patameters:

View file

@ -127,6 +127,32 @@ class MIHMzansiWalletApis {
// }
}
/// This function is used to Delete loyalty card from users mzansi wallet.
///
/// Patameters:-
/// AppUser signedInUser,
/// int idloyalty_cards,
/// BuildContext context,
///
/// Returns VOID (TRIGGERS NOTIGICATIOPN ON SUCCESS)
static Future<int?> deleteLoyaltyCardAPICallV2(
int idloyalty_cards,
) async {
try {
var response = await http.delete(
Uri.parse(
"${AppEnviroment.baseApiUrl}/mzasni-wallet/loyalty-cards/delete/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{"idloyalty_cards": idloyalty_cards}),
);
return response.statusCode;
} catch (error) {
return null;
}
}
/// This function is used to add a lopyalty card to users mzansi wallet.
///
/// Patameters:-
@ -187,6 +213,48 @@ class MIHMzansiWalletApis {
// }
}
/// This function is used to add a lopyalty card to users mzansi wallet.
///
/// Patameters:-
/// AppUser signedInUser,
/// String app_id,
/// String shop_name,
/// String card_number,
/// BuildContext context,
///
/// Returns VOID (TRIGGERS SUCCESS pop up)
static Future<int?> addLoyaltyCardAPICallV2(
String app_id,
String shop_name,
String card_number,
String favourite,
int priority_index,
String nickname,
) async {
try {
var response = await http
.post(
Uri.parse(
"${AppEnviroment.baseApiUrl}/mzasni-wallet/loyalty-cards/insert/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"app_id": app_id,
"shop_name": shop_name,
"card_number": card_number,
"favourite": favourite,
"priority_index": priority_index,
"nickname": nickname,
}),
)
.timeout(const Duration(seconds: 5));
return response.statusCode;
} catch (error) {
return null;
}
}
/// This function is used to Update loyalty card from users mzansi wallet.
///
/// Patameters:-
@ -238,6 +306,42 @@ class MIHMzansiWalletApis {
return response.statusCode;
}
/// This function is used to Update loyalty card from users mzansi wallet.
///
/// Patameters:-
/// AppUser signedInUser,
/// int idloyalty_cards,
/// BuildContext context,
///
/// Returns VOID (TRIGGERS NOTIGICATIOPN ON SUCCESS)
static Future<int?> updateLoyaltyCardAPICallV2(
int idloyalty_cards,
String favourite,
int priority_index,
String nickname,
String card_number,
) async {
try {
var response = await http.put(
Uri.parse(
"${AppEnviroment.baseApiUrl}/mzasni-wallet/loyalty-cards/update/"),
headers: <String, String>{
"Content-Type": "application/json; charset=UTF-8"
},
body: jsonEncode(<String, dynamic>{
"idloyalty_cards": idloyalty_cards,
"favourite": favourite,
"priority_index": priority_index,
"nickname": nickname,
"card_number": card_number,
}),
);
return response.statusCode;
} catch (error) {
return null;
}
}
//================== POP UPS ==========================================================================
static void loadingPopUp(BuildContext context) {