From bfadb3fe14ebd24dd3ef0ab79ee4dbef4d944b0c Mon Sep 17 00:00:00 2001 From: MhdZiadHirati Date: Tue, 24 Oct 2023 15:40:09 +0300 Subject: [PATCH] appointment ux optimiazation --- lib/core/localization/localization.dart | 11 +- .../widgets/appointment_details.dart | 111 ++++++++++++++++-- .../business_logic_layer/home_controller.dart | 24 ++++ 3 files changed, 135 insertions(+), 11 deletions(-) diff --git a/lib/core/localization/localization.dart b/lib/core/localization/localization.dart index d54190b..bfe7c91 100644 --- a/lib/core/localization/localization.dart +++ b/lib/core/localization/localization.dart @@ -4,6 +4,11 @@ class PagesTranslations implements Translations { @override Map> get keys => { 'en': { + 'appointment_canceling': 'Appontiment Canceling', + 'are_you_sure_?': 'Are You Sure?', + 'appointment_canceled_successfully': + 'Appointment Canceled Successfully', + 'cancel': 'Cancel', 'appointment': 'Appointment', 'you_have_an_appointment_on': 'You have An Appointment on', 'appointment_scheduled_successfully.': @@ -18,7 +23,6 @@ class PagesTranslations implements Translations { 'no_previous_conversations_!': 'No Previous Conversations !', 'add_some_by_contact_with_others': 'Add Some By Contact With Others', 'this_session_is_terminated': 'This session is terminated', - 'cancel': 'Cancel', "log_out_from_other_devices": "Log out from other devices", 'version_update': 'Version Update', 'new_version_is_available_!': 'New Version is Available !', @@ -191,6 +195,10 @@ class PagesTranslations implements Translations { 'Enter your email to reset your password please \n We will send verification code to your Email.', }, 'ar': { + 'appointment_canceling': 'إلغاء الموعد', + 'are_you_sure_?': 'هل أنت متأكد؟', + 'appointment_canceled_successfully': 'تم إلغاء الموعد بنجاح', + 'cancel': 'الغاء', 'appointment': 'موعد', 'you_have_an_appointment_on': 'لديك موعد بتاريخ', 'appointment_scheduled_successfully.': 'تم حجز الموعد بنجاح', @@ -205,7 +213,6 @@ class PagesTranslations implements Translations { 'add_some_by_contact_with_others': 'أضف بعضها عن طريق التواصل مع الآخرين', "this_session_is_terminated": "تم إنهاء هذه الجلسة", - "cancel": "إلغاء", "log_out_from_other_devices": "تسجيل الخروج من الأجهزة الأخرى", 'version_update': 'تحديث الإصدار', 'new_version_is_available_!': 'الإصدار الجديد متاح!', diff --git a/lib/features/card/presentation_layer/widgets/appointment_details.dart b/lib/features/card/presentation_layer/widgets/appointment_details.dart index f969b02..922aa8a 100644 --- a/lib/features/card/presentation_layer/widgets/appointment_details.dart +++ b/lib/features/card/presentation_layer/widgets/appointment_details.dart @@ -1,6 +1,10 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; +import 'package:taafee_mobile/common/widgets/button.dart'; +import 'package:taafee_mobile/common/widgets/toast.dart'; +import 'package:taafee_mobile/core/routing/routing_manager.dart'; +import 'package:taafee_mobile/features/card/data_layer/model/appointment.dart'; import '../../../../common/const/const.dart'; import '../../../../common/widgets/text.dart'; @@ -9,16 +13,16 @@ import '../../../home/business_logic_layer/home_controller.dart'; class AppointmentDetails extends StatelessWidget { AppointmentDetails({ super.key, - required this.dateTime, + required this.appointment, }); - final DateTime dateTime; + final Appointment appointment; final HomeController homeController = Get.find(); @override Widget build(BuildContext context) { return SizedBox( width: 320, - height: 240, + height: 280, child: Column( children: [ const SizedBox( @@ -39,11 +43,14 @@ class AppointmentDetails extends StatelessWidget { ), child: Column( children: [ - RegularTextWidget( - DateFormat.EEEE().format(dateTime).tr, + BoldTextWidget( + DateFormat.EEEE().format(appointment.dateTime).tr, fontSize: 15, color: Colors.white, ), + const SizedBox( + height: 16, + ), Row( children: [ const Icon( @@ -51,12 +58,15 @@ class AppointmentDetails extends StatelessWidget { color: Colors.white, ), RegularTextWidget( - ' ${dateTime.day} / ${dateTime.month}', + ' ${appointment.dateTime.day} / ${appointment.dateTime.month}', fontSize: 15, color: Colors.white, ), ], ), + const SizedBox( + height: 8, + ), Row( children: [ const Icon( @@ -65,21 +75,104 @@ class AppointmentDetails extends StatelessWidget { ), if (!homeController.isArabic.value) RegularTextWidget( - ' ${dateTime.hour % 12} : ${dateTime.minute >= 10 ? dateTime.minute : '0${dateTime.minute}'} ${(dateTime.hour <= 12) ? 'am'.tr : 'pm'.tr}', + ' ${appointment.dateTime.hour % 12} : ${appointment.dateTime.minute >= 10 ? appointment.dateTime.minute : '0${appointment.dateTime.minute}'} ${(appointment.dateTime.hour <= 12) ? 'am'.tr : 'pm'.tr}', color: Colors.white, fontSize: 15, ), if (homeController.isArabic.value) RegularTextWidget( - ' ${dateTime.minute >= 10 ? dateTime.minute : '0${dateTime.minute}'} : ${dateTime.hour % 12} ${(dateTime.hour <= 12) ? 'am'.tr : 'pm'.tr}', + ' ${appointment.dateTime.minute >= 10 ? appointment.dateTime.minute : '0${appointment.dateTime.minute}'} : ${appointment.dateTime.hour % 12} ${(appointment.dateTime.hour <= 12) ? 'am'.tr : 'pm'.tr}', color: Colors.white, fontSize: 15, ), ], ), + const SizedBox( + height: 8, + ), ], ), - ).paddingSymmetric(horizontal: 16) + ).paddingSymmetric(horizontal: 16), + const SizedBox( + height: 16, + ), + Obx(() { + return ButtonWidget( + isLoading: homeController.appointmentCancelingState.loading, + width: 250, + onTap: () async { + bool cancel = false; + await showDialog( + context: context, + builder: (context) { + return AlertDialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20)), + contentPadding: EdgeInsets.zero, + actionsPadding: EdgeInsets.zero, + title: BoldTextWidget( + 'appointment_canceling'.tr, + fontSize: 18, + textAlign: TextAlign.center, + ), + content: SizedBox( + height: 280, + width: 320, + child: Column( + children: [ + const SizedBox( + height: 56, + ), + RegularTextWidget( + 'are_you_sure_?'.tr, + fontSize: 16, + textAlign: TextAlign.center, + ), + const SizedBox( + height: 24, + ), + SizedBox( + width: 300, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceEvenly, + children: [ + ButtonWidget( + width: 100, + onTap: () { + cancel = true; + RoutingManager.back(); + }, + color: AppColors.redColor, + title: 'yes'.tr), + ButtonWidget( + width: 100, + color: AppColors.secondaryColor + .withOpacity(0.7), + onTap: () { + cancel = false; + RoutingManager.back(); + }, + title: 'no'.tr), + ], + ), + ) + ], + ), + ), + ); + }); + if (cancel) { + homeController.cancelAppointment(onSuccess: () { + Toast.showToast('appointment_canceled_successfully'.tr); + RoutingManager.back(); + }); + } + }, + title: 'cancel'.tr, + color: AppColors.redColor, + ); + }), ], ), ); diff --git a/lib/features/home/business_logic_layer/home_controller.dart b/lib/features/home/business_logic_layer/home_controller.dart index 0b340d3..4546552 100644 --- a/lib/features/home/business_logic_layer/home_controller.dart +++ b/lib/features/home/business_logic_layer/home_controller.dart @@ -209,6 +209,30 @@ class HomeController extends GetxController { ); } + RxFuture appointmentCancelingState = RxFuture(null); + + void cancelAppointment({void Function()? onSuccess}) { + appointmentCancelingState.observe( + (value) async { + await Future.delayed(const Duration(seconds: 3)); + }, + onSuccess: (response) async { + user.update((val) { + int index = val!.appointments!.lastIndexWhere((element) => + element.cardId == currentCardAppointment.value!.cardId); + val.appointments!.removeAt(index); + }); + + await storage.setAppointments(user.value!.appointments!); + + currentCardAppointment = null.obs; + currentCardAppointment.refresh(); + user.refresh(); + onSuccess?.call(); + }, + ); + } + Appointment? getCardAppointment(int cardId) { if (user.value!.appointments == null || user.value!.appointments!.isEmpty) { return null;