appointments ui and caching

This commit is contained in:
MhdZiadHirati 2023-10-19 17:26:07 +03:00
parent ecd3e791c2
commit e00f0354dd
13 changed files with 292 additions and 76 deletions

View File

@ -16,6 +16,7 @@ class ButtonWidget extends StatelessWidget {
final bool? isLoading;
final double? buttonHeight;
final bool hideTextOnLoading;
final double? fontSize;
const ButtonWidget(
{super.key,
required this.onTap,
@ -27,6 +28,7 @@ class ButtonWidget extends StatelessWidget {
this.loaderColor,
this.width,
this.buttonHeight,
this.fontSize,
this.textColor,
this.isLoading = false});
@ -44,6 +46,7 @@ class ButtonWidget extends StatelessWidget {
child ?? Container(),
BoldTextWidget(
title,
fontSize: fontSize,
color: Colors.white,
).paddingSymmetric(horizontal: 10),
])
@ -58,6 +61,8 @@ class ButtonWidget extends StatelessWidget {
isLoading!),
child: BoldTextWidget(
title,
fontSize: fontSize,
textAlign: TextAlign.center,
color: Colors.white,
).paddingSymmetric(horizontal: 20),
),
@ -72,6 +77,8 @@ class ButtonWidget extends StatelessWidget {
)
: BoldTextWidget(
title,
fontSize: fontSize,
textAlign: TextAlign.center,
color: Colors.white,
),
).onTap(() {

View File

@ -1,8 +1,10 @@
import 'dart:convert';
import 'dart:developer';
import 'package:get_storage/get_storage.dart';
import '../../features/auth/data_layer/model/user.dart';
import '../../features/card/data_layer/model/appointment.dart';
class LocalStorage {
final GetStorage storage = GetStorage();
@ -76,4 +78,31 @@ class LocalStorage {
Future<void> clearCache() async {
await storage.erase();
}
Future<void> setAppointments(List<Appointment> appointments) async {
for (int i = 0; i < appointments.length; i++) {
await storage.write(
'appointments[$i]', jsonEncode(appointments[i].toJson()));
}
await storage.write('appointments_length', appointments.length);
}
List<Appointment>? getAppointments() {
int appointmentsLength = storage.read('appointments_length') ?? 0;
if (appointmentsLength == 0) {
return null;
} else {
List<Appointment> appointments = [];
for (int i = 0; i < appointmentsLength; i++) {
appointments.add(
Appointment.fromJson(
jsonDecode(
storage.read('appointments[$i]'),
),
),
);
}
return appointments;
}
}
}

View File

@ -4,7 +4,8 @@ class PagesTranslations implements Translations {
@override
Map<String, Map<String, String>> get keys => {
'en': {
'schedule_an_appointment': 'Schedule an appointment',
'you_have_an_appointment_on': 'your appointment on',
'schedule_an_appointment': 'Appointment',
'There are no notifications to display at this time.':
'There are no notifications to display at this time.',
'no_previous_conversations_!': 'No Previous Conversations !',
@ -183,7 +184,8 @@ class PagesTranslations implements Translations {
'Enter your email to reset your password please \n We will send verification code to your Email.',
},
'ar': {
'schedule_an_appointment': 'جدولة موعد',
'you_have_an_appointment_on': 'لديك موعد بتاريخ',
'schedule_an_appointment': 'حجز موعد',
'There are no notifications to display at this time.':
'لا توجد إشعارات لعرضها في الوقت الحالي.',
'no_previous_conversations_!': 'لا توجد محادثات سابقة!',

View File

@ -33,7 +33,7 @@ class AccountScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
accountController.getSelectedLanguageIcon();
homeController.readUser();
// homeController.readUser();
return Scaffold(
backgroundColor: AppColors.backGroundColor,
body: SingleChildScrollView(

View File

@ -1,3 +1,5 @@
import 'package:taafee_mobile/features/card/data_layer/model/appointment.dart';
class User {
int id;
String firstName;
@ -5,6 +7,7 @@ class User {
String email;
int chatUserId;
String? avatarImage;
List<Appointment>? appointments;
User({
required this.id,
required this.firstName,
@ -12,6 +15,7 @@ class User {
required this.email,
required this.avatarImage,
required this.chatUserId,
this.appointments,
});
factory User.fromJson(Map<String, dynamic> json) => User(

View File

@ -5,6 +5,7 @@ import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:taafee_mobile/common/const/const.dart';
import 'package:taafee_mobile/core/local_storage/local_storage.dart';
import 'package:taafee_mobile/features/card/data_layer/model/add_card.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_images.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_model.dart';
@ -17,6 +18,7 @@ import '../../../core/utils/pagination_list.dart';
class CardController extends GetxController {
//---------------data source-----------//
CardService cardService = CardService();
LocalStorage localStorage = LocalStorage();
//----------- model-----------//
Rx<AddCardModel> cardModel = AddCardModel.zero().obs;

View File

@ -0,0 +1,41 @@
import '../../../auth/data_layer/model/user.dart';
class Appointment {
DateTime dateTime;
int cardId;
User user;
Appointment(
{required this.cardId, required this.dateTime, required this.user});
factory Appointment.fromJson(Map<String, dynamic> jsonMap) => Appointment(
cardId: jsonMap['card_id'],
dateTime: DateTime.parse(jsonMap['date']),
user: User.fromJson(jsonMap['user']));
Map<String, dynamic> toJson() => {
"card_id": cardId,
"date": dateTime.toString(),
"user": user.toJson(),
};
static List<Appointment> fromJsonList(List jsonList) {
List<Appointment> appointments = [];
// ignore: avoid_function_literals_in_foreach_calls
jsonList.forEach((element) {
appointments.add(Appointment.fromJson(element));
});
return appointments;
}
static List<Map<String, dynamic>> toJsonList(List<Appointment> appointments) {
List<Map<String, dynamic>> jsonList = [];
// ignore: avoid_function_literals_in_foreach_calls
appointments.forEach((element) {
jsonList.add(element.toJson());
});
return jsonList;
}
@override
toString() {
return 'card_id:$cardId,userName:${user.firstName},date:${dateTime.toString()}';
}
}

View File

@ -7,6 +7,7 @@ import 'package:taafee_mobile/common/widgets/button.dart';
import 'package:taafee_mobile/common/widgets/text.dart';
import 'package:taafee_mobile/core/routing/routing_manager.dart';
import 'package:taafee_mobile/features/card/business_logic_layer/card_controller.dart';
import 'package:taafee_mobile/features/card/data_layer/model/appointment.dart';
import 'package:taafee_mobile/features/card/presentation_layer/widgets/card_details.dart';
import 'package:taafee_mobile/features/card/presentation_layer/widgets/card_service.dart';
import 'package:taafee_mobile/features/chat/business%20logic%20layer/chat_controller.dart';
@ -199,6 +200,9 @@ class CardDetailsScreen extends StatelessWidget {
],
),
),
const SizedBox(
height: 40,
),
Row(
children: [
ButtonWidget(
@ -215,7 +219,7 @@ class CardDetailsScreen extends StatelessWidget {
const ColorFilter.mode(Colors.white, BlendMode.srcIn),
),
)
.paddingSymmetric(horizontal: 10)
.paddingSymmetric(horizontal: 4)
.expanded(Responsive.isTablet() ? 1 : 5),
ButtonWidget(
color: AppColors.emailColor,
@ -227,7 +231,7 @@ class CardDetailsScreen extends StatelessWidget {
textColor: Colors.white,
child: SvgPicture.asset("assets/icons/Email.svg"),
)
.paddingSymmetric(horizontal: 10)
.paddingSymmetric(horizontal: 4)
.expanded(Responsive.isTablet() ? 1 : 5),
if (Responsive.isTablet())
Visibility(
@ -257,15 +261,78 @@ class CardDetailsScreen extends StatelessWidget {
).expanded(2);
}),
),
if (Responsive.isTablet())
Visibility(
visible: homeController.user.value!.id != cardModel.user.id,
child: ButtonWidget(
onTap: () {
homeController.scheduleAnAppointment(
Appointment(
cardId: cardModel.id,
dateTime: DateTime.now(),
user: homeController.user.value!),
);
},
haveIcon: true,
title: 'schedule_an_appointment'.tr,
color: AppColors.secondaryColor,
child: const Icon(
Icons.schedule,
color: Colors.white,
),
)
.paddingSymmetric(horizontal: 10)
.expanded(Responsive.isTablet() ? 1 : 5),
),
],
).paddingSymmetric(
vertical: Responsive.isTablet() ? 20 : 10,
vertical: Responsive.isTablet() ? 20 : 4,
horizontal: Responsive.isTablet() ? 40 : 10),
if (!Responsive.isTablet())
Obx(() {
return Row(
children: [
Obx(() {
return Visibility(
visible:
homeController.user.value!.id != cardModel.user.id,
child:
(homeController.currentCardAppointment.value != null)
? ButtonWidget(
onTap: () {},
fontSize: 12,
color: AppColors.secondaryColor,
title:
'${'you_have_an_appointment_on'.tr} ${homeController.currentCardAppointment.value!.dateTime.toString().substring(0, 11)}',
)
.paddingSymmetric(horizontal: 4)
.expanded(Responsive.isTablet() ? 1 : 5)
: ButtonWidget(
onTap: () {
homeController.scheduleAnAppointment(
Appointment(
cardId: cardModel.id,
dateTime: DateTime.now(),
user: homeController.user.value!),
);
},
haveIcon: true,
fontSize: 12,
title: 'schedule_an_appointment'.tr,
color: AppColors.secondaryColor,
child: const Icon(
Icons.schedule,
color: Colors.white,
),
)
.paddingSymmetric(horizontal: 4)
.expanded(Responsive.isTablet() ? 1 : 5),
);
}),
Visibility(
visible: chatController.chatUser.id != cardModel.user.chatUserId,
child: Obx(() {
return ButtonWidget(
visible:
chatController.chatUser.id != cardModel.user.chatUserId,
child: ButtonWidget(
isLoading: chatController.createRoomState.loading,
textColor: Colors.white,
color: AppColors.messageColor,
@ -284,13 +351,20 @@ class CardDetailsScreen extends StatelessWidget {
}
},
title: "start_conversation".tr,
fontSize: 12,
child: SvgPicture.asset("assets/icons/message.svg"),
);
}),
)
.paddingSymmetric(horizontal: 4)
.expanded(Responsive.isTablet() ? 1 : 5),
),
],
).paddingSymmetric(
vertical: Responsive.isTablet() ? 20 : 4,
horizontal: Responsive.isTablet() ? 40 : 10);
}),
const SizedBox(
height: 60,
)
),
],
).paddingSymmetric(horizontal: Responsive.isTablet() ? 20 : 0)),
).makeSafeArea();

View File

@ -7,14 +7,15 @@ import 'package:taafee_mobile/common/extensions/widget_extension.dart';
import 'package:taafee_mobile/common/widgets/text.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_model.dart';
import 'package:taafee_mobile/features/card/presentation_layer/widgets/card_location.dart';
import 'package:taafee_mobile/features/home/business_logic_layer/home_controller.dart';
import '../../../../core/routing/routing_manager.dart';
import 'card_header.dart';
class FirstCardWidget extends StatelessWidget {
final CardModel cardModel;
const FirstCardWidget(this.cardModel, {super.key});
final HomeController homeController = Get.find<HomeController>();
FirstCardWidget(this.cardModel, {super.key});
@override
Widget build(BuildContext context) {
return Container(
@ -95,6 +96,7 @@ class FirstCardWidget extends StatelessWidget {
),
],
).onTap(() {
homeController.setCardAppointment(cardModel.id);
RoutingManager.to(RouteName.cardDetails, arguments: cardModel);
}),
],

View File

@ -70,6 +70,7 @@ class MyCardWidget extends StatelessWidget {
),
],
).onTap(() {
homeController.setCardAppointment(cardModel.id);
RoutingManager.to(RouteName.cardDetails, arguments: cardModel);
}),
],

View File

@ -6,13 +6,15 @@ import 'package:taafee_mobile/common/extensions/widget_extension.dart';
import 'package:taafee_mobile/common/widgets/text.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_model.dart';
import 'package:taafee_mobile/features/card/presentation_layer/widgets/card_header.dart';
import 'package:taafee_mobile/features/home/business_logic_layer/home_controller.dart';
import '../../../../common/const/const.dart';
import '../../../../core/routing/routing_manager.dart';
class SecondCardWidget extends StatelessWidget {
final CardModel cardModel;
const SecondCardWidget(this.cardModel, {super.key});
final HomeController homeController = Get.find<HomeController>();
SecondCardWidget(this.cardModel, {super.key});
@override
Widget build(BuildContext context) {
@ -92,6 +94,7 @@ class SecondCardWidget extends StatelessWidget {
).paddingSymmetric(horizontal: 5),
],
).onTap(() {
homeController.setCardAppointment(cardModel.id);
RoutingManager.to(RouteName.cardDetails, arguments: cardModel);
}),
),

View File

@ -11,10 +11,12 @@ import 'package:taafee_mobile/core/routing/routing_manager.dart';
import 'package:taafee_mobile/features/card/business_logic_layer/card_controller.dart';
import 'package:taafee_mobile/features/favorite/business_logic_layer/favorite_controller.dart';
import 'package:taafee_mobile/features/favorite/presentation_layer/widgets/favorite_card.dart';
import 'package:taafee_mobile/features/home/business_logic_layer/home_controller.dart';
class FavoriteScreen extends StatelessWidget {
final CardController cardController = Get.find<CardController>();
final FavoriteController favoriteController = Get.find<FavoriteController>();
final HomeController homeController = Get.find<HomeController>();
FavoriteScreen({super.key});
@override
@ -41,8 +43,8 @@ class FavoriteScreen extends StatelessWidget {
width: Get.width,
height: Get.height * 0.75,
rxFuture: favoriteController.getFavoriteState,
child: () =>
(favoriteController.getFavoriteState.result.isNotEmpty)
child: () => (favoriteController
.getFavoriteState.result.isNotEmpty)
? GridViewWidget(
mainAxisExtent: 150,
count: Responsive.isTablet() ? 3 : 2,
@ -50,12 +52,14 @@ class FavoriteScreen extends StatelessWidget {
favoriteController.getFavoriteState.result.length,
child: (index) => Obx(() {
return FavoriteCardWidget(
favoriteModel: favoriteController
.getFavoriteState.result[index],
favoriteModel:
favoriteController.getFavoriteState.result[index],
).onTap(() {
homeController.setCardAppointment(favoriteController
.getFavoriteState.result[index].cardModel.id);
RoutingManager.to(RouteName.cardDetails,
arguments: favoriteController.getFavoriteState
.result[index].cardModel);
arguments: favoriteController
.getFavoriteState.result[index].cardModel);
});
}),
)

View File

@ -6,6 +6,7 @@ import 'package:taafee_mobile/common/widgets/button.dart';
import 'package:taafee_mobile/common/widgets/text.dart';
import 'package:taafee_mobile/core/local_storage/local_storage.dart';
import 'package:taafee_mobile/core/routing/routing_manager.dart';
import 'package:taafee_mobile/features/card/data_layer/model/appointment.dart';
import 'package:taafee_mobile/features/card/data_layer/model/card_model.dart';
import 'package:taafee_mobile/features/home/data_layer/model/city.dart';
import 'package:taafee_mobile/features/home/data_layer/model/search.dart';
@ -50,7 +51,6 @@ class HomeController extends GetxController {
}
//------------read user----------////
//pick avatar image
Rx<File?> pickedUserImage = null.obs;
RxBool isAvatarImagePicked = false.obs;
@ -64,7 +64,12 @@ class HomeController extends GetxController {
} else {
isUserHasAvatar.value = false;
}
List<Appointment>? appointments = storage.getAppointments();
if (appointments != null) {
user.update((val) {
val!.appointments = appointments;
});
}
user.refresh();
isUserHasAvatar.refresh();
}
@ -167,4 +172,46 @@ class HomeController extends GetxController {
}
isArabic.refresh();
}
/// ----------- schedule an appointment -------///
Rx<Appointment?> currentCardAppointment = null.obs;
void setCardAppointment(int cardId) {
currentCardAppointment = getCardAppointment(cardId).obs;
currentCardAppointment.refresh();
user.refresh();
}
void scheduleAnAppointment(Appointment appointment) async {
user.update((val) {
if (val!.appointments != null) {
val.appointments!.add(appointment);
} else {
val.appointments = [];
val.appointments!.add(appointment);
}
});
try {
await storage.setAppointments(user.value!.appointments!);
print(user.value!.appointments);
} catch (error) {
print(error.toString());
}
currentCardAppointment = appointment.obs;
currentCardAppointment.refresh();
print('currentCardAppointment:${currentCardAppointment.value}');
user.refresh();
}
Appointment? getCardAppointment(int cardId) {
if (user.value!.appointments == null || user.value!.appointments!.isEmpty) {
return null;
}
print('user appointments: ${user.value!.appointments!}');
Appointment? appointment = user.value!.appointments!
.firstWhereOrNull((element) => (element.cardId == cardId));
print('current appointment:$appointment');
return appointment;
}
}