diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index 6465e96..b6262f6 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -509,7 +509,68 @@ "selectCategory": "اختر الفئة", "searchByService": "البحث حسب الخدمة", "selectServices": "اختر الخدمات", - "modifyPackage": "تعديل الحزمة" + "modifyPackage": "تعديل الحزمة", + "schedule": "الجدول", + "serviceLocation": "موقع الخدمة:", + "workshop": "ورشة العمل", + "itemsSelected": "العناصر المحددة", + "workshopFullAccessServices": "بعض الخدمات غير متوفرة في الموقع المنزلي. قم بتغيير الموقع إلى ورشة العمل للوصول الكامل إلى الخدمات", + "changeLocationService": "تغيير الموقع أو الخدمة:", + "noItemstoShow": "لا توجد عناصر لعرضها.", + "someDescriptionSubServices": "بعض الوصف عن الخدمات الفرعية", + "selectServicesYouWant": "اختر الخدمات التي تريدها", + "selectServiceType": "اختر نوع الخدمة", + "selectDateAndTime": "اختر التاريخ والوقت", + "reviewAppointment": "مراجعة الموعد", + "carEngineCheck": "فحص محرك السيارة", + "dateAndTime": "التاريخ والوقت", + "timeLocation": "الوقت والموقع", + "serviceCharges": "رسوم الخدمة", + "locationCharges": "رسوم الموقع", + "payableNow": "المبلغ المستحق الآن", + "remainingAmount": "المبلغ المتبقي", + "branchesFilter": "تصفية الفروع", + "searchByDistance": "البحث حسب المسافة", + "searchByMinimumRatings": "البحث حسب التقييمات الأدنى", + "chat": "الدردشة", + "noRequestsShow": "لا توجد طلبات لعرضها.", + "typeMessageHere": "اكتب رسالتك هنا..", + "reject": "رفض", + "newOfferRequired": "مطلوب عرض جديد", + "offerHasBeenAccepted": "تم قبول العرض", + "offerHasBeenRejected": "تم رفض العرض", + "offerHasBeenCancelled": "تم إلغاء العرض", + "paymentMethod": "طريقة الدفع", + "selectPaymentMethod": "اختر طريقة الدفع", + "password": "كلمة المرور", + "customerName": "اسم العميل", + "createRequest": "إنشاء طلب", + "requestType": "نوع الطلب", + "brand": "العلامة التجارية", + "year": "السنة", + "price": "السعر", + "shippingDelivery": "الشحن/التسليم", + "offers": "العروض", + "noOffersShow": "لا توجد عروض لعرضها", + "allDocumentMandatoryDealershipProvider": "جميع المستندات إلزامية لمقدم خدمات الوكالة", + "documentsUploadedSuccessfully": "تم تحميل المستندات بنجاح", + "help": "المساعدة", + "faqs": "الأسئلة الشائعة", + "contactUs": "اتصل بنا", + "termPrivacy": "الشروط والخصوصية", + "inviteFriends": "دعوة الأصدقاء", + "more": "المزيد", + "language": "اللغة", + "mySubscriptions": "اشتراكاتي", + "subscriptions": "الاشتراكات", + "defineLicenses": "تحديد التراخيص", + "logOut": "تسجيل الخروج", + "customer": "العميل", + "accept": "قبول" + + + + diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index 2e3fe63..ea99de6 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -510,14 +510,62 @@ "selectCategory":"Select Category", "searchByService":"Search By Service", "selectServices":"Select Services", - "modifyPackage": "Modify Package" - - - - - - - - - + "modifyPackage": "Modify Package", + "schedule": "Schedule", + "serviceLocation": "Service Location:", + "workshop": "Workshop", + "itemsSelected": "Item(s) Selected", + "workshopFullAccessServices": "Few services are not available on home location. Change the location to workshop to full access the services", + "changeLocationService": "Change location or service:", + "noItemstoShow": "No Items to show.", + "someDescriptionSubServices": "Some description about the sub-services", + "selectServicesYouWant": "Select services you want", + "selectServiceType": "Select service type", + "selectDateAndTime": "Select date and time", + "reviewAppointment": "Review Appointment", + "carEngineCheck": "Car Engine Check", + "dateAndTime": "Date and Time", + "timeLocation": "Time & Location", + "serviceCharges": "Service Charges", + "locationCharges" : "Location Charges", + "payableNow": "Payable Now", + "remainingAmount": "Remaining Amount", + "branchesFilter": "Branches Filter", +"searchByDistance": "Search By Distance", + "searchByMinimumRatings": "Search By Minimum Ratings", +"chat": "Chat", + "noRequestsShow": "No Requests to show.", + "typeMessageHere": "Type your message here..", + "reject": "Reject", + "newOfferRequired": "New Offer Required", + "offerHasBeenAccepted": "Offer has been accepted", + "offerHasBeenRejected": "Offer has been rejected", + "offerHasBeenCancelled": "Offer has been cancelled", + "paymentMethod": "Payment Method", + "selectPaymentMethod": "Select Payment Method", + "password": "Password", + "customerName": "Customer Name", + "createRequest": "Create Request", + "requestType": "Request Type", + "brand": "Brand", + "year": "Year", + "price": "Price", + "shippingDelivery": "Shipping/Delivery", + "offers": "Offers", + "noOffersShow": "No Offers to show", + "allDocumentMandatoryDealershipProvider": "All document's are mandatory for Dealership Provider", + "documentsUploadedSuccessfully": "Documents uploaded successfully", + "help": "Help", + "faqs": "FAQs", + "contactUs": "Contact Us", + "termPrivacy": "Term & Privacy", + "inviteFriends": "Invite Friends", + "more": "More", + "language" :"Language", + "mySubscriptions": "My Subscriptions", + "subscriptions": "Subscriptions", + "defineLicenses": "Define Licenses", + "logOut": "Log Out", + "customer": "Customer", + "accept": "Accept" } \ No newline at end of file diff --git a/lib/generated/codegen_loader.g.dart b/lib/generated/codegen_loader.g.dart index daf3498..8f4e664 100644 --- a/lib/generated/codegen_loader.g.dart +++ b/lib/generated/codegen_loader.g.dart @@ -525,7 +525,64 @@ class CodegenLoader extends AssetLoader{ "selectCategory": "اختر الفئة", "searchByService": "البحث حسب الخدمة", "selectServices": "اختر الخدمات", - "modifyPackage": "تعديل الحزمة" + "modifyPackage": "تعديل الحزمة", + "schedule": "الجدول", + "serviceLocation": "موقع الخدمة:", + "workshop": "ورشة العمل", + "itemsSelected": "العناصر المحددة", + "workshopFullAccessServices": "بعض الخدمات غير متوفرة في الموقع المنزلي. قم بتغيير الموقع إلى ورشة العمل للوصول الكامل إلى الخدمات", + "changeLocationService": "تغيير الموقع أو الخدمة:", + "noItemstoShow": "لا توجد عناصر لعرضها.", + "someDescriptionSubServices": "بعض الوصف عن الخدمات الفرعية", + "selectServicesYouWant": "اختر الخدمات التي تريدها", + "selectServiceType": "اختر نوع الخدمة", + "selectDateAndTime": "اختر التاريخ والوقت", + "reviewAppointment": "مراجعة الموعد", + "carEngineCheck": "فحص محرك السيارة", + "dateAndTime": "التاريخ والوقت", + "timeLocation": "الوقت والموقع", + "serviceCharges": "رسوم الخدمة", + "locationCharges": "رسوم الموقع", + "payableNow": "المبلغ المستحق الآن", + "remainingAmount": "المبلغ المتبقي", + "branchesFilter": "تصفية الفروع", + "searchByDistance": "البحث حسب المسافة", + "searchByMinimumRatings": "البحث حسب التقييمات الأدنى", + "chat": "الدردشة", + "noRequestsShow": "لا توجد طلبات لعرضها.", + "typeMessageHere": "اكتب رسالتك هنا..", + "reject": "رفض", + "newOfferRequired": "مطلوب عرض جديد", + "offerHasBeenAccepted": "تم قبول العرض", + "offerHasBeenRejected": "تم رفض العرض", + "offerHasBeenCancelled": "تم إلغاء العرض", + "paymentMethod": "طريقة الدفع", + "selectPaymentMethod": "اختر طريقة الدفع", + "password": "كلمة المرور", + "customerName": "اسم العميل", + "createRequest": "إنشاء طلب", + "requestType": "نوع الطلب", + "brand": "العلامة التجارية", + "year": "السنة", + "price": "السعر", + "shippingDelivery": "الشحن/التسليم", + "offers": "العروض", + "noOffersShow": "لا توجد عروض لعرضها", + "allDocumentMandatoryDealershipProvider": "جميع المستندات إلزامية لمقدم خدمات الوكالة", + "documentsUploadedSuccessfully": "تم تحميل المستندات بنجاح", + "help": "المساعدة", + "faqs": "الأسئلة الشائعة", + "contactUs": "اتصل بنا", + "termPrivacy": "الشروط والخصوصية", + "inviteFriends": "دعوة الأصدقاء", + "more": "المزيد", + "language": "اللغة", + "mySubscriptions": "اشتراكاتي", + "subscriptions": "الاشتراكات", + "defineLicenses": "تحديد التراخيص", + "logOut": "تسجيل الخروج", + "customer": "العميل", + "accept": "قبول" }; static const Map en_US = { "firstTimeLogIn": "First Time Log In", @@ -1039,7 +1096,64 @@ static const Map en_US = { "selectCategory": "Select Category", "searchByService": "Search By Service", "selectServices": "Select Services", - "modifyPackage": "Modify Package" + "modifyPackage": "Modify Package", + "schedule": "Schedule", + "serviceLocation": "Service Location:", + "workshop": "Workshop", + "itemsSelected": "Item(s) Selected", + "workshopFullAccessServices": "Few services are not available on home location. Change the location to workshop to full access the services", + "changeLocationService": "Change location or service:", + "noItemstoShow": "No Items to show.", + "someDescriptionSubServices": "Some description about the sub-services", + "selectServicesYouWant": "Select services you want", + "selectServiceType": "Select service type", + "selectDateAndTime": "Select date and time", + "reviewAppointment": "Review Appointment", + "carEngineCheck": "Car Engine Check", + "dateAndTime": "Date and Time", + "timeLocation": "Time & Location", + "serviceCharges": "Service Charges", + "locationCharges": "Location Charges", + "payableNow": "Payable Now", + "remainingAmount": "Remaining Amount", + "branchesFilter": "Branches Filter", + "searchByDistance": "Search By Distance", + "searchByMinimumRatings": "Search By Minimum Ratings", + "chat": "Chat", + "noRequestsShow": "No Requests to show.", + "typeMessageHere": "Type your message here..", + "reject": "Reject", + "newOfferRequired": "New Offer Required", + "offerHasBeenAccepted": "Offer has been accepted", + "offerHasBeenRejected": "Offer has been rejected", + "offerHasBeenCancelled": "Offer has been cancelled", + "paymentMethod": "Payment Method", + "selectPaymentMethod": "Select Payment Method", + "password": "Password", + "customerName": "Customer Name", + "createRequest": "Create Request", + "requestType": "Request Type", + "brand": "Brand", + "year": "Year", + "price": "Price", + "shippingDelivery": "Shipping/Delivery", + "offers": "Offers", + "noOffersShow": "No Offers to show", + "allDocumentMandatoryDealershipProvider": "All document's are mandatory for Dealership Provider", + "documentsUploadedSuccessfully": "Documents uploaded successfully", + "help": "Help", + "faqs": "FAQs", + "contactUs": "Contact Us", + "termPrivacy": "Term & Privacy", + "inviteFriends": "Invite Friends", + "more": "More", + "language": "Language", + "mySubscriptions": "My Subscriptions", + "subscriptions": "Subscriptions", + "defineLicenses": "Define Licenses", + "logOut": "Log Out", + "customer": "Customer", + "accept": "Accept" }; static const Map> mapLocales = {"ar_SA": ar_SA, "en_US": en_US}; } diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 3551f58..355108c 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -489,5 +489,62 @@ abstract class LocaleKeys { static const searchByService = 'searchByService'; static const selectServices = 'selectServices'; static const modifyPackage = 'modifyPackage'; + static const schedule = 'schedule'; + static const serviceLocation = 'serviceLocation'; + static const workshop = 'workshop'; + static const itemsSelected = 'itemsSelected'; + static const workshopFullAccessServices = 'workshopFullAccessServices'; + static const changeLocationService = 'changeLocationService'; + static const noItemstoShow = 'noItemstoShow'; + static const someDescriptionSubServices = 'someDescriptionSubServices'; + static const selectServicesYouWant = 'selectServicesYouWant'; + static const selectServiceType = 'selectServiceType'; + static const selectDateAndTime = 'selectDateAndTime'; + static const reviewAppointment = 'reviewAppointment'; + static const carEngineCheck = 'carEngineCheck'; + static const dateAndTime = 'dateAndTime'; + static const timeLocation = 'timeLocation'; + static const serviceCharges = 'serviceCharges'; + static const locationCharges = 'locationCharges'; + static const payableNow = 'payableNow'; + static const remainingAmount = 'remainingAmount'; + static const branchesFilter = 'branchesFilter'; + static const searchByDistance = 'searchByDistance'; + static const searchByMinimumRatings = 'searchByMinimumRatings'; + static const chat = 'chat'; + static const noRequestsShow = 'noRequestsShow'; + static const typeMessageHere = 'typeMessageHere'; + static const reject = 'reject'; + static const newOfferRequired = 'newOfferRequired'; + static const offerHasBeenAccepted = 'offerHasBeenAccepted'; + static const offerHasBeenRejected = 'offerHasBeenRejected'; + static const offerHasBeenCancelled = 'offerHasBeenCancelled'; + static const paymentMethod = 'paymentMethod'; + static const selectPaymentMethod = 'selectPaymentMethod'; + static const password = 'password'; + static const customerName = 'customerName'; + static const createRequest = 'createRequest'; + static const requestType = 'requestType'; + static const brand = 'brand'; + static const year = 'year'; + static const price = 'price'; + static const shippingDelivery = 'shippingDelivery'; + static const offers = 'offers'; + static const noOffersShow = 'noOffersShow'; + static const allDocumentMandatoryDealershipProvider = 'allDocumentMandatoryDealershipProvider'; + static const documentsUploadedSuccessfully = 'documentsUploadedSuccessfully'; + static const help = 'help'; + static const faqs = 'faqs'; + static const contactUs = 'contactUs'; + static const termPrivacy = 'termPrivacy'; + static const inviteFriends = 'inviteFriends'; + static const more = 'more'; + static const language = 'language'; + static const mySubscriptions = 'mySubscriptions'; + static const subscriptions = 'subscriptions'; + static const defineLicenses = 'defineLicenses'; + static const logOut = 'logOut'; + static const customer = 'customer'; + static const accept = 'accept'; } diff --git a/lib/view_models/subscriptions_view_model.dart b/lib/view_models/subscriptions_view_model.dart index d6a31a5..49e6d5e 100644 --- a/lib/view_models/subscriptions_view_model.dart +++ b/lib/view_models/subscriptions_view_model.dart @@ -27,15 +27,13 @@ class SubscriptionsVM extends BaseVM { getAllAvailableSubscriptions(String? serviceProviderID) async { selectedIndex = 0; setState(ViewState.busy); - allSubscriptions = - await subscriptionRepo.getAllSubscriptions(serviceProviderID); + allSubscriptions = await subscriptionRepo.getAllSubscriptions(serviceProviderID); if (allSubscriptions.messageStatus == 1) { monthlyTabs.clear(); var idSet = {}; for (var d in allSubscriptions.data ?? []) { if (idSet.add(d.durationDays ?? 0)) { - monthlyTabs.add(DropValue( - d.durationDays, _convertDaysToMonths(d.durationDays ?? 0), "")); + monthlyTabs.add(DropValue(d.durationDays, _convertDaysToMonths(d.durationDays ?? 0), "")); } } monthlyTabs.sort((a, b) => a.value.compareTo(b.value)); @@ -50,15 +48,13 @@ class SubscriptionsVM extends BaseVM { getSubscriptionBySP(String serviceProviderID, bool isRenew) async { selectedIndex = 0; setState(ViewState.busy); - allSubscriptions = - await subscriptionRepo.getSubscriptionBySP(serviceProviderID, isRenew); + allSubscriptions = await subscriptionRepo.getSubscriptionBySP(serviceProviderID, isRenew); if (allSubscriptions.messageStatus == 1) { monthlyTabs.clear(); var idSet = {}; for (var d in allSubscriptions.data ?? []) { if (idSet.add(d.durationDays ?? 0)) { - monthlyTabs.add(DropValue( - d.durationDays, _convertDaysToMonths(d.durationDays ?? 0), "")); + monthlyTabs.add(DropValue(d.durationDays, _convertDaysToMonths(d.durationDays ?? 0), "")); } } monthlyTabs.sort((a, b) => a.value.compareTo(b.value)); @@ -72,11 +68,9 @@ class SubscriptionsVM extends BaseVM { String newPrice = ""; - calculationUpgradePrice( - String? serviceProviderID, String? newSubscription) async { + calculationUpgradePrice(String? serviceProviderID, String? newSubscription) async { setState(ViewState.busy); - MResponse mResponse = await subscriptionRepo.calculationUpgradePrice( - serviceProviderID, newSubscription); + MResponse mResponse = await subscriptionRepo.calculationUpgradePrice(serviceProviderID, newSubscription); if (mResponse.messageStatus == 1) { setState(ViewState.idle); newPrice = mResponse.data.toString(); @@ -85,18 +79,13 @@ class SubscriptionsVM extends BaseVM { } } - Future payForSubscription( - int subscriptionId, bool isStartNow, bool isReview, String amount, - {bool isDegrade = false, - List? listOfBranches, - List? listOfUsers}) async { + Future payForSubscription(int subscriptionId, bool isStartNow, bool isReview, String amount, {bool isDegrade = false, List? listOfBranches, List? listOfUsers}) async { Map map; if (isDegrade) { map = { // "id": subscription.id.toString(), // "payFortOrderID": 0, - "providerID": - AppState().getUser.data?.userInfo?.providerId.toString() ?? "", + "providerID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "", "subscriptionID": subscriptionId.toString(), "isStartNow": isStartNow.toString(), "subscriptionAmount": amount, @@ -108,8 +97,7 @@ class SubscriptionsVM extends BaseVM { map = { // "id": subscription.id.toString(), // "payFortOrderID": 0, - "providerID": - AppState().getUser.data?.userInfo?.providerId.toString() ?? "", + "providerID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "", "subscriptionID": subscriptionId.toString(), "isStartNow": isStartNow.toString(), "subscriptionAmount": amount, @@ -118,8 +106,23 @@ class SubscriptionsVM extends BaseVM { // "listOfUsers": [] }; } - MResponse mResponse = - await subscriptionRepo.payForProviderSubscription(map); + MResponse mResponse = await subscriptionRepo.payForProviderSubscription(map); + return mResponse; + } + + Future createSubscriptionOrder(int subscriptionId, bool isStartNow, bool isReview, String amount, {bool isDegrade = false, List? listOfBranches, List? listOfUsers}) async { + Map map = { + // "id": subscription.id.toString(), + // "payFortOrderID": 0, + "providerID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "", + "subscriptionID": subscriptionId.toString(), + "isStartNow": isStartNow.toString(), + "subscriptionAmount": amount, + "isRenew": isReview.toString() + // "listOfBranches": [], + // "listOfUsers": [] + }; + MResponse mResponse = await subscriptionRepo.payForProviderSubscription(map); return mResponse; } @@ -130,8 +133,7 @@ class SubscriptionsVM extends BaseVM { Map map = { // "id": subscription.id.toString(), // "payFortOrderID": 0, - "providerID": - AppState().getUser.data?.userInfo?.providerId.toString() ?? "", + "providerID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "", // "listOfBranches": [], // "listOfUsers": [] }; @@ -146,12 +148,8 @@ class SubscriptionsVM extends BaseVM { final int months = days ~/ 30; final int remainingDays = days % 30; - String _result = months > 0 - ? '$months Month${months > 1 ? 's' : ''}${remainingDays > 0 ? ' & ' : ''}' - : ''; - _result += remainingDays > 0 - ? '$remainingDays Day${remainingDays > 1 ? 's' : ''}' - : ''; + String _result = months > 0 ? '$months Month${months > 1 ? 's' : ''}${remainingDays > 0 ? ' & ' : ''}' : ''; + _result += remainingDays > 0 ? '$remainingDays Day${remainingDays > 1 ? 's' : ''}' : ''; return _result; } @@ -169,8 +167,7 @@ class SubscriptionsVM extends BaseVM { selectedIndex = 0; setState(ViewState.busy); // allSubscriptions = await subscriptionRepo.getAllSubscriptions(serviceProviderID); - allSubscriptions = - await subscriptionRepo.getMySubscriptions(serviceProviderID); + allSubscriptions = await subscriptionRepo.getMySubscriptions(serviceProviderID); if (allSubscriptions.messageStatus == 1) { // allSubscriptions.data!.sort((a, b) => a.value.compareTo(b.value)); setState(ViewState.idle); diff --git a/lib/view_models/user_view_model.dart b/lib/view_models/user_view_model.dart index 6c7c2d3..27e45d6 100644 --- a/lib/view_models/user_view_model.dart +++ b/lib/view_models/user_view_model.dart @@ -53,6 +53,14 @@ class UserVM extends BaseVM { bool completeProfilePageCheckbox = false; + bool _loginOtherAccount = false; + + bool get loginOtherAccount => _loginOtherAccount; + + set loginOtherAccount(bool value) { + _loginOtherAccount = value; + } + void updateCompleteProfilePageCheckbox(bool newValue) { completeProfilePageCheckbox = newValue; notifyListeners(); @@ -155,8 +163,7 @@ class UserVM extends BaseVM { } } - Future performCompleteProfile( - BuildContext context, { + Future performCompleteProfile(BuildContext context, { required String password, required String confirmPassword, required String firstName, @@ -515,8 +522,8 @@ class UserVM extends BaseVM { type == ClassType.NUMBER && countryCode != null ? countryCode + phoneNum : type == ClassType.NUMBER && countryCode == null - ? phoneNum - : phoneNum, + ? phoneNum + : phoneNum, password); Utils.hideLoading(context); LoginPasswordRespModel user = LoginPasswordRespModel.fromJson(jsonDecode(response.body)); @@ -524,8 +531,8 @@ class UserVM extends BaseVM { SharedPrefManager.setPhoneOrEmail(type == ClassType.NUMBER && countryCode != null ? countryCode + phoneNum : type == ClassType.NUMBER && countryCode == null - ? phoneNum - : phoneNum); + ? phoneNum + : phoneNum); SharedPrefManager.setUserPassword(password); navigateReplaceWithName(context, AppRoutes.loginMethodSelection, arguments: user.data!.userToken); } else { @@ -620,9 +627,7 @@ class UserVM extends BaseVM { Future isAlreadyUserLoggedin(BuildContext context) async { String uName = await SharedPrefManager.getPhoneOrEmail(); String pass = await SharedPrefManager.getUserPassword(); - - if (uName.isNotEmpty && pass.isNotEmpty) { - logger.d(uName); + if (!loginOtherAccount && uName.isNotEmpty && pass.isNotEmpty) { if (uName.isNum()) { performBasicOtpLoginWithPasswordPage(context, type: ClassType.NUMBER, countryCode: null, phoneNum: uName, password: pass); } @@ -632,4 +637,9 @@ class UserVM extends BaseVM { logger.d("Skip Login Triggered"); } } + + void otherLogin(BuildContext context) { + _loginOtherAccount = true; + navigateReplaceWithName(context, AppRoutes.loginWithPassword); + } } diff --git a/lib/views/appointments/book_appointment_schedules_view.dart b/lib/views/appointments/book_appointment_schedules_view.dart index 37738f4..234cb9c 100644 --- a/lib/views/appointments/book_appointment_schedules_view.dart +++ b/lib/views/appointments/book_appointment_schedules_view.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart'; import 'package:mc_common_app/models/services_models/service_model.dart'; import 'package:mc_common_app/theme/colors.dart'; @@ -11,6 +12,7 @@ import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/common_widgets/time_slots.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; class ScreenArgumentsForAppointmentDetailPage { final int routeFlag; // 1 = coming from create appointment || 2 = coming from reschedule appointment @@ -28,7 +30,7 @@ class BookAppointmentSchedulesView extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: "Book Appointment", + title: LocaleKeys.bookAppointment.tr(), isRemoveBackButton: false, isDrawerEnabled: false, onBackButtonTapped: () => Navigator.pop(context), @@ -52,15 +54,15 @@ class BookAppointmentSchedulesView extends StatelessWidget { Row( children: [ Expanded( - child: "Schedule ${scheduleIndex + 1}".toText(fontSize: 20, isBold: true), + child: (LocaleKeys.schedule.tr() + " ${scheduleIndex + 1}").toText(fontSize: 20, isBold: true), ), ], ), Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Service Location: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - ("${scheduleData.appointmentType == 2 ? "Home" : "Workshop"}").toText(fontSize: 12, isBold: true).expand(), + (LocaleKeys.serviceLocation.tr()).toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + ("${scheduleData.appointmentType == 2 ? LocaleKeys.home.tr() : LocaleKeys.workshop.tr()}").toText(fontSize: 12, isBold: true).expand(), ], ), Column( @@ -100,7 +102,7 @@ class BookAppointmentSchedulesView extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - ("Available Slots").toText(fontSize: 14, isBold: true), + (LocaleKeys.availableSlots.tr()).toText(fontSize: 14, isBold: true), ], ), 5.height, @@ -128,7 +130,7 @@ class BookAppointmentSchedulesView extends StatelessWidget { child: ShowFillButton( txtColor: MyColors.black, maxHeight: 55, - title: "Cancel", + title: LocaleKeys.cancel.tr(), onPressed: () => Navigator.pop(context), backgroundColor: MyColors.greyButtonColor, ), @@ -137,7 +139,7 @@ class BookAppointmentSchedulesView extends StatelessWidget { Expanded( child: ShowFillButton( maxHeight: 55, - title: screenArgumentsForAppointmentDetailPage.routeFlag == 1 ? "Review" : "Confirm", + title: screenArgumentsForAppointmentDetailPage.routeFlag == 1 ? LocaleKeys.review.tr() : LocaleKeys.confirm.tr(), onPressed: () { if (screenArgumentsForAppointmentDetailPage.routeFlag == 1) { appointmentsVM.onReviewButtonPressed(context); diff --git a/lib/views/appointments/book_appointment_services_view.dart b/lib/views/appointments/book_appointment_services_view.dart index ae38cd3..909734e 100644 --- a/lib/views/appointments/book_appointment_services_view.dart +++ b/lib/views/appointments/book_appointment_services_view.dart @@ -1,6 +1,9 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/services_models/item_model.dart'; import 'package:mc_common_app/models/services_models/service_model.dart'; import 'package:mc_common_app/theme/colors.dart'; @@ -10,6 +13,7 @@ import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; class BookAppointmentServicesView extends StatelessWidget { BookAppointmentServicesView({Key? key}) : super(key: key); @@ -18,7 +22,7 @@ class BookAppointmentServicesView extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: "Book Appointment", + title: LocaleKeys.bookAppointment.tr(), isRemoveBackButton: false, isDrawerEnabled: false, onBackButtonTapped: () { @@ -27,7 +31,8 @@ class BookAppointmentServicesView extends StatelessWidget { }, ), body: Consumer( - builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { + builder: (BuildContext context, AppointmentsVM appointmentsVM, + Widget? child) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -35,12 +40,14 @@ class BookAppointmentServicesView extends StatelessWidget { CustomAddButton( needsBorder: true, bgColor: MyColors.white, - onTap: () => appointmentsVM.openTheAddServiceBottomSheet(context, appointmentsVM), - text: "Add Services", + onTap: () => appointmentsVM.openTheAddServiceBottomSheet( + context, appointmentsVM), + text: LocaleKeys.addServices.tr(), icon: Container( height: 24, width: 24, - decoration: const BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor), + decoration: const BoxDecoration( + shape: BoxShape.circle, color: MyColors.darkTextColor), child: const Icon(Icons.add, color: MyColors.white), ), ).horPaddingMain(), @@ -49,17 +56,22 @@ class BookAppointmentServicesView extends StatelessWidget { shrinkWrap: true, itemCount: appointmentsVM.servicesInCurrentAppointment.length, itemBuilder: (BuildContext context, int serviceIndex) { - ServiceModel serviceData = appointmentsVM.servicesInCurrentAppointment[serviceIndex]; + ServiceModel serviceData = appointmentsVM + .servicesInCurrentAppointment[serviceIndex]; return Column( children: [ Row( children: [ Expanded( - child: (serviceData.serviceDescription ?? "").toText(fontSize: 15, isBold: true), + child: (serviceData.serviceDescription ?? "") + .toText(fontSize: 15, isBold: true), ), IconButton( - onPressed: () => appointmentsVM.removeServiceInCurrentAppointment(serviceIndex), - icon: Icon(Icons.delete_outline, color: MyColors.redColor), + onPressed: () => appointmentsVM + .removeServiceInCurrentAppointment( + serviceIndex), + icon: Icon(Icons.delete_outline, + color: MyColors.redColor), ) ], ), @@ -67,19 +79,33 @@ class BookAppointmentServicesView extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Service Location: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - (serviceData.isHomeSelected ? serviceData.homeLocation : "Workshop").toText(fontSize: 12, isBold: true).expand(), + (LocaleKeys.serviceLocation.tr()).toText( + fontSize: 12, + color: MyColors.lightTextColor, + isBold: true), + (serviceData.isHomeSelected + ? serviceData.homeLocation + : LocaleKeys.workshop.tr()) + .toText(fontSize: 12, isBold: true) + .expand(), ], ), 5.height, Column( - children: List.generate(serviceData.serviceItems!.length, (itemIndex) { - ItemData itemData = serviceData.serviceItems![itemIndex]; + children: List.generate( + serviceData.serviceItems!.length, (itemIndex) { + ItemData itemData = + serviceData.serviceItems![itemIndex]; return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "${itemData.name}: ".toText(fontSize: 13, color: MyColors.lightTextColor, isBold: true), - ("${itemData.price}").toText(fontSize: 13, isBold: true).expand(), + "${itemData.name}: ".toText( + fontSize: 13, + color: MyColors.lightTextColor, + isBold: true), + ("${itemData.price}") + .toText(fontSize: 13, isBold: true) + .expand(), ], ); }), @@ -88,18 +114,33 @@ class BookAppointmentServicesView extends StatelessWidget { Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - ((appointmentsVM.servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice).toString()).toText(fontSize: 32, isBold: true), + ((appointmentsVM + .servicesInCurrentAppointment[ + serviceIndex] + .currentTotalServicePrice) + .toString()) + .toText(fontSize: 32, isBold: true), 2.width, - "SAR".toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5), - Icon( - Icons.arrow_drop_down, - size: 30, - ) + LocaleKeys.sar + .tr() + .toText( + color: MyColors.lightTextColor, + fontSize: 16, + isBold: true) + .paddingOnly(bottom: 5), + Icon(Icons.arrow_drop_down, size: 30) ], - ).onPress(() => appointmentsVM.priceBreakDownClicked(context, appointmentsVM.servicesInCurrentAppointment[serviceIndex])), + ).onPress(() => appointmentsVM.priceBreakDownClicked( + context, + appointmentsVM + .servicesInCurrentAppointment[serviceIndex])), ], ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10)); + ).toWhiteContainer( + width: double.infinity, + allPading: 12, + margin: const EdgeInsets.symmetric( + horizontal: 21, vertical: 10)); }, ).expand(), Row( @@ -108,7 +149,7 @@ class BookAppointmentServicesView extends StatelessWidget { child: ShowFillButton( txtColor: MyColors.black, maxHeight: 55, - title: "Cancel", + title: LocaleKeys.cancel.tr(), onPressed: () { appointmentsVM.servicesInCurrentAppointment.clear(); appointmentsVM.allSelectedItemsInAppointments.clear(); @@ -121,7 +162,7 @@ class BookAppointmentServicesView extends StatelessWidget { Expanded( child: ShowFillButton( maxHeight: 55, - title: "Next", + title: LocaleKeys.next.tr(), onPressed: () { appointmentsVM.onServicesNextPressed(context); }, diff --git a/lib/views/appointments/book_appointments_item_view.dart b/lib/views/appointments/book_appointments_item_view.dart index 09f892f..f234a60 100644 --- a/lib/views/appointments/book_appointments_item_view.dart +++ b/lib/views/appointments/book_appointments_item_view.dart @@ -1,8 +1,8 @@ - import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/services_models/item_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/navigator.dart'; @@ -12,6 +12,7 @@ import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; class BookAppointmentsItemView extends StatelessWidget { const BookAppointmentsItemView({Key? key}) : super(key: key); @@ -20,14 +21,15 @@ class BookAppointmentsItemView extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: "Select Items", + title: LocaleKeys.selectItems.tr(), isRemoveBackButton: false, isDrawerEnabled: false, actions: [MyAssets.searchIcon.buildSvg().paddingOnly(right: 21)], onBackButtonTapped: () => Navigator.pop(context), ), body: Consumer( - builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { + builder: (BuildContext context, AppointmentsVM appointmentsVM, + Widget? child) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -36,18 +38,30 @@ class BookAppointmentsItemView extends StatelessWidget { width: double.infinity, color: MyColors.darkTextColor, alignment: Alignment.centerLeft, - child: "${appointmentsVM.selectedSubServicesCounter} Item(s) Selected".toText(fontSize: 16, color: MyColors.white).horPaddingMain(), + child: ("${appointmentsVM.selectedSubServicesCounter} " + + LocaleKeys.itemsSelected.tr()) + .toText(fontSize: 16, color: MyColors.white) + .horPaddingMain(), ), 16.height, Column( children: [ - "Few services are not available on home location. Change the location to workshop to full access the services".toText(fontSize: 12, isItalic: true, color: MyColors.lightTextColor), + LocaleKeys.workshopFullAccessServices.tr().toText( + fontSize: 12, + isItalic: true, + color: MyColors.lightTextColor), 8.height, Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Change location or service: ".toText(fontSize: 14, isBold: true), - "Edit".toText(fontSize: 14, isBold: true, isUnderLine: true, color: MyColors.adPendingStatusColor), + LocaleKeys.changeLocationService + .tr() + .toText(fontSize: 14, isBold: true), + LocaleKeys.edit.tr().toText( + fontSize: 14, + isBold: true, + isUnderLine: true, + color: MyColors.adPendingStatusColor), 5.width, MyAssets.icEdit.buildSvg(width: 17), ], @@ -57,26 +71,41 @@ class BookAppointmentsItemView extends StatelessWidget { ], ).horPaddingMain(), appointmentsVM.serviceItemsFromApi.isEmpty - ? Expanded(child: Center(child: "No Items to show.".toText(fontSize: 16, color: MyColors.lightTextColor))) + ? Expanded( + child: Center( + child: LocaleKeys.noItemstoShow.toText( + fontSize: 16, color: MyColors.lightTextColor))) : ListView.separated( - separatorBuilder: (BuildContext context, int index) => Divider(), + separatorBuilder: (BuildContext context, int index) => + Divider(), itemCount: appointmentsVM.serviceItemsFromApi.length, itemBuilder: (BuildContext context, int index) { - ItemData itemData = appointmentsVM.serviceItemsFromApi[index]; + ItemData itemData = + appointmentsVM.serviceItemsFromApi[index]; return ServiceItemWithPriceCheckBox( - description: itemData.description ?? "Some description about the sub-services", + description: itemData.description ?? + LocaleKeys.someDescriptionSubServices.tr(), title: itemData.name!, isSelected: itemData.isUpdateOrSelected!, onSelection: (bool value) { print("itemId: ${itemData.id}"); - appointmentsVM.onItemUpdateOrSelected(index, !itemData.isUpdateOrSelected!, itemData.id!); + appointmentsVM.onItemUpdateOrSelected(index, + !itemData.isUpdateOrSelected!, itemData.id!); }, priceWidget: Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - // TODO: This Price will be decided according to the service selected - itemData.price!.split(".").first.toText(fontSize: 30, isBold: true), - " SAR".toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5), + itemData.price! + .split(".") + .first + .toText(fontSize: 30, isBold: true), + LocaleKeys.sar + .tr() + .toText( + fontSize: 15, + isBold: true, + color: MyColors.lightTextColor) + .paddingOnly(bottom: 5), ], ), ); @@ -93,7 +122,8 @@ class BookAppointmentsItemView extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.end, children: [ - appointmentsVM.selectSubServicesError.toText(fontSize: 14, color: Colors.red), + appointmentsVM.selectSubServicesError + .toText(fontSize: 14, color: Colors.red), ], ).paddingOnly(right: 10), 8.height, @@ -103,9 +133,10 @@ class BookAppointmentsItemView extends StatelessWidget { child: ShowFillButton( txtColor: MyColors.black, maxHeight: 55, - title: "Cancel", + title: LocaleKeys.cancel.tr(), onPressed: () { - appointmentsVM.resetCategorySelectionBottomSheet(); + appointmentsVM + .resetCategorySelectionBottomSheet(); pop(context); }, backgroundColor: MyColors.greyButtonColor, @@ -117,9 +148,10 @@ class BookAppointmentsItemView extends StatelessWidget { builder: (BuildContext context) { return ShowFillButton( maxHeight: 55, - title: "Next", + title: LocaleKeys.next.tr(), onPressed: () async { - bool resp = appointmentsVM.validateItemsSelection(); + bool resp = + appointmentsVM.validateItemsSelection(); if (resp) { appointmentsVM.onItemsSelectedInService(); Navigator.pop(context); @@ -133,7 +165,10 @@ class BookAppointmentsItemView extends StatelessWidget { // Navigator.of(context).pushReplacementNamed(AppRoutes.bookAppointmenServicesView); // } }, - backgroundColor: !appointmentsVM.isServiceSelectionValidated() ? MyColors.lightTextColor.withOpacity(0.6) : MyColors.darkPrimaryColor, + backgroundColor: !appointmentsVM + .isServiceSelectionValidated() + ? MyColors.lightTextColor.withOpacity(0.6) + : MyColors.darkPrimaryColor, ); }, ), diff --git a/lib/views/appointments/pick_items_view.dart b/lib/views/appointments/pick_items_view.dart index bd8c1e6..053e6d2 100644 --- a/lib/views/appointments/pick_items_view.dart +++ b/lib/views/appointments/pick_items_view.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; @@ -9,6 +10,7 @@ import 'package:mc_common_app/widgets/common_widgets/provider_details_card.dart' import 'package:mc_common_app/widgets/common_widgets/time_slots.dart'; import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:easy_localization/easy_localization.dart'; class BookProviderAppView extends StatefulWidget { const BookProviderAppView({Key? key}) : super(key: key); @@ -24,7 +26,7 @@ class _BookProviderAppViewState extends State { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: "Appointment", + title: LocaleKeys.appointment.tr(), profileImageUrl: MyAssets.bnCar, isRemoveBackButton: false, isDrawerEnabled: false, @@ -46,7 +48,9 @@ class _BookProviderAppViewState extends State { providerRatings: "4.9", ), 12.height, - isReview ? ReviewAppointmentSection() : ServicesSelectionSection(), + isReview + ? ReviewAppointmentSection() + : ServicesSelectionSection(), 10.height, ], ), @@ -55,7 +59,7 @@ class _BookProviderAppViewState extends State { Padding( padding: const EdgeInsets.only(bottom: 10, left: 21, right: 21), child: ShowFillButton( - title: "Book Appointment", + title: LocaleKeys.bookAppointment.tr(), maxWidth: double.infinity, onPressed: () { isReview = !isReview; @@ -87,44 +91,47 @@ class ServicesSelectionSection extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Select services you want".toText(fontSize: 18, isBold: true), + LocaleKeys.selectServicesYouWant + .tr() + .toText(fontSize: 18, isBold: true), 8.height, DropdownField( (DropValue value) {}, list: dropList, - hint: "Select service type", + hint: LocaleKeys.selectServiceType.tr(), ), 8.height, DropdownField( (DropValue value) {}, list: dropList, - hint: "Select service type", + hint: LocaleKeys.selectServiceType.tr(), ), 8.height, DropdownField( (DropValue value) {}, list: dropList, - hint: "Select service type", + hint: LocaleKeys.selectServiceType.tr(), ), 22.height, - "Select date and time".toText(fontSize: 18, isBold: true), + LocaleKeys.selectDateAndTime.tr().toText(fontSize: 18, isBold: true), 8.height, DropdownField( (DropValue value) {}, list: dropList, - hint: "Select service type", + hint: LocaleKeys.selectServiceType.tr(), ), 22.height, - "Available slots".toText(fontSize: 15, isBold: true), + LocaleKeys.availableSlots.tr().toText(fontSize: 15, isBold: true), 8.height, BuildTimeSlots(onPressed: (index) {}, timeSlots: []), 22.height, - "Total Amount".toText(fontSize: 18, isBold: true), + LocaleKeys.totalAmount.tr().toText(fontSize: 18, isBold: true), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ "3000".toText(fontSize: 20, isBold: true), - "SAR".toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor), + LocaleKeys.sar.tr().toText( + fontSize: 10, isBold: true, color: MyColors.lightTextColor), ], ), 10.height, @@ -144,20 +151,24 @@ class ReviewAppointmentSection extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Review Appointment".toText(fontSize: 18, isBold: true), + LocaleKeys.reviewAppointment.tr().toText(fontSize: 18, isBold: true), 15.height, - "Services".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), - "Car Engine Check".toText(fontSize: 18, isBold: true), + LocaleKeys.services.tr().toText( + fontSize: 14, isBold: true, color: MyColors.lightTextColor), + LocaleKeys.carEngineCheck.tr().toText(fontSize: 18, isBold: true), 13.height, - "Date and Time".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + LocaleKeys.dateAndTime.tr().toText( + fontSize: 14, isBold: true, color: MyColors.lightTextColor), "2 Feb, 2023 at 09:00am".toText(fontSize: 18, isBold: true), 13.height, - "Total Amount".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + LocaleKeys.totalAmount.tr().toText( + fontSize: 14, isBold: true, color: MyColors.lightTextColor), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ "3000".toText(fontSize: 20, isBold: true), - "SAR".toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor), + LocaleKeys.sar.tr().toText( + fontSize: 10, isBold: true, color: MyColors.lightTextColor), ], ), 100.height, diff --git a/lib/views/appointments/review_appointment_view.dart b/lib/views/appointments/review_appointment_view.dart index 75fbe46..57b81c7 100644 --- a/lib/views/appointments/review_appointment_view.dart +++ b/lib/views/appointments/review_appointment_view.dart @@ -1,6 +1,6 @@ - import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/widgets.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; @@ -48,12 +48,17 @@ class ReviewAppointment extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ - (appointmentsVM.selectedBranchModel!.branchName ?? "").toText(fontSize: 16, isBold: true), + (appointmentsVM.selectedBranchModel!.branchName ?? + "") + .toText(fontSize: 16, isBold: true), Row( children: [ - LocaleKeys.location.tr().toText(color: MyColors.lightTextColor, fontSize: 12), + LocaleKeys.location.tr().toText( + color: MyColors.lightTextColor, + fontSize: 12), 2.width, - ": ${appointmentsVM.selectedBranchModel!.branchDescription ?? ""}".toText(fontSize: 12), + ": ${appointmentsVM.selectedBranchModel!.branchDescription ?? ""}" + .toText(fontSize: 12), ], ), ], @@ -77,7 +82,9 @@ class ReviewAppointment extends StatelessWidget { ), ), ], - ).onPress(() {}).toWhiteContainer(width: double.infinity, allPading: 12)); + ) + .onPress(() {}) + .toWhiteContainer(width: double.infinity, allPading: 12)); } Widget buildServicesInfoCard({required BuildContext context}) { @@ -86,14 +93,18 @@ class ReviewAppointment extends StatelessWidget { shrinkWrap: true, itemCount: appointmentsVM.serviceAppointmentScheduleList.length, itemBuilder: (BuildContext context, int scheduleIndex) { - ServiceAppointmentScheduleModel scheduleData = appointmentsVM.serviceAppointmentScheduleList[scheduleIndex]; + ServiceAppointmentScheduleModel scheduleData = + appointmentsVM.serviceAppointmentScheduleList[scheduleIndex]; return Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( - child: "Services".toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor), + child: LocaleKeys.services.tr().toText( + fontSize: 14, + isBold: true, + color: MyColors.lightTextColor), ), ], ), @@ -106,33 +117,55 @@ class ReviewAppointment extends StatelessWidget { itemCount: scheduleData.servicesListInAppointment!.length, itemBuilder: (BuildContext context, int serviceIndex) { String selectedTimeSlot = ""; - if (scheduleData.selectedCustomTimeDateSlotModel!.availableSlots != null) { - selectedTimeSlot = scheduleData.selectedCustomTimeDateSlotModel!.availableSlots!.firstWhere((element) => element.isSelected).slot; + if (scheduleData + .selectedCustomTimeDateSlotModel!.availableSlots != + null) { + selectedTimeSlot = scheduleData + .selectedCustomTimeDateSlotModel!.availableSlots! + .firstWhere((element) => element.isSelected) + .slot; } return Column( children: [ - if (scheduleData.servicesListInAppointment!.isNotEmpty) ...[ + if (scheduleData + .servicesListInAppointment!.isNotEmpty) ...[ Column( - children: List.generate(scheduleData.servicesListInAppointment!.length, (serviceIndex) { - ServiceModel serviceData = scheduleData.servicesListInAppointment![serviceIndex]; + children: List.generate( + scheduleData.servicesListInAppointment!.length, + (serviceIndex) { + ServiceModel serviceData = scheduleData + .servicesListInAppointment![serviceIndex]; return Column( children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - "${serviceData.providerServiceDescription}".toText(fontSize: 16, isBold: true), + "${serviceData.providerServiceDescription}" + .toText(fontSize: 16, isBold: true), ], ), Column( - children: List.generate(serviceData.serviceItems!.length, (itemIndex) { - ItemData itemData = serviceData.serviceItems![itemIndex]; + children: List.generate( + serviceData.serviceItems!.length, + (itemIndex) { + ItemData itemData = + serviceData.serviceItems![itemIndex]; return Column( children: [ Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, children: [ - "${itemData.name}: ${itemData.price} SAR".toText(fontSize: 13, isBold: true, color: MyColors.lightTextColor), + ("${itemData.name}: ${itemData.price} " + + LocaleKeys.sar.tr()) + .toText( + fontSize: 13, + isBold: true, + color: MyColors + .lightTextColor), ], ), ], @@ -150,15 +183,27 @@ class ReviewAppointment extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Time & Location".toText(fontSize: 16, isBold: true), + LocaleKeys.timeLocation + .tr() + .toText(fontSize: 16, isBold: true), 3.height, Row(children: [ - "Date & Time: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - "${scheduleData.selectedCustomTimeDateSlotModel!.date!.date} at ${selectedTimeSlot}".toText(fontSize: 12, isBold: true), + LocaleKeys.dateAndTime.tr().toText( + fontSize: 12, + color: MyColors.lightTextColor, + isBold: true), + "${scheduleData.selectedCustomTimeDateSlotModel!.date!.date} at ${selectedTimeSlot}" + .toText(fontSize: 12, isBold: true), ]), Row(children: [ - "Location: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), - (scheduleData.appointmentType == 2 ? "Home" : "Workshop").toText(fontSize: 12, isBold: true), + (LocaleKeys.location.tr() + " ").toText( + fontSize: 12, + color: MyColors.lightTextColor, + isBold: true), + (scheduleData.appointmentType == 2 + ? LocaleKeys.home.tr() + : LocaleKeys.workshop.tr()) + .toText(fontSize: 12, isBold: true), ]), ], ), @@ -174,20 +219,35 @@ class ReviewAppointment extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Amount".toText(fontSize: 16, isBold: true), + LocaleKeys.amount + .tr() + .toText(fontSize: 16, isBold: true), Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - "Service Charges".toText(fontSize: 14, color: MyColors.lightTextColor, isBold: true), - "${scheduleData.amountTotal.toString()} SAR".toText(fontSize: 16, isBold: true), + LocaleKeys.serviceCharges.tr().toText( + fontSize: 14, + color: MyColors.lightTextColor, + isBold: true), + "${scheduleData.amountTotal.toString()} SAR" + .toText(fontSize: 16, isBold: true), ], ), if (scheduleData.appointmentType == 1) ...[ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - "Location Charges ($rangePricePerKm x $totalKms )".toText(fontSize: 14, color: MyColors.lightTextColor, isBold: true), - "${totalServicePrice.toString()} SAR".toText(fontSize: 16, isBold: true), + (LocaleKeys.locationCharges.tr() + + " ($rangePricePerKm x $totalKms )") + .toText( + fontSize: 14, + color: MyColors.lightTextColor, + isBold: true), + ("${totalServicePrice.toString()} " + + LocaleKeys.sar.tr()) + .toText(fontSize: 16, isBold: true), ], ), ], @@ -198,12 +258,16 @@ class ReviewAppointment extends StatelessWidget { ], ); }, - separatorBuilder: (BuildContext context, int index) => Divider(thickness: 2), + separatorBuilder: (BuildContext context, int index) => + Divider(thickness: 2), ).paddingOnly(bottom: 10), ], ), ], - ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 0)); + ).toWhiteContainer( + width: double.infinity, + allPading: 12, + margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 0)); }, ); } @@ -221,13 +285,21 @@ class ReviewAppointment extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - "Payable now".toText(fontSize: 14, isBold: true), + LocaleKeys.payableNow.tr().toText(fontSize: 14, isBold: true), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - appointmentsVM.amountToPayForAppointment.toString().toText(fontSize: 16, isBold: true), + appointmentsVM.amountToPayForAppointment + .toString() + .toText(fontSize: 16, isBold: true), 2.width, - "SAR".toText(color: MyColors.lightTextColor, fontSize: 12, isBold: true).paddingOnly(bottom: 2), + LocaleKeys.sar + .tr() + .toText( + color: MyColors.lightTextColor, + fontSize: 12, + isBold: true) + .paddingOnly(bottom: 2), ], ) ], @@ -235,13 +307,24 @@ class ReviewAppointment extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - "Remaining Amount".toText(fontSize: 14, isBold: true), + LocaleKeys.remainingAmount + .tr() + .toText(fontSize: 14, isBold: true), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - (appointmentsVM.totalAmount - appointmentsVM.amountToPayForAppointment).toString().toText(fontSize: 16, isBold: true), + (appointmentsVM.totalAmount - + appointmentsVM.amountToPayForAppointment) + .toString() + .toText(fontSize: 16, isBold: true), 2.width, - "SAR".toText(color: MyColors.lightTextColor, fontSize: 12, isBold: true).paddingOnly(bottom: 2), + LocaleKeys.sar + .tr() + .toText( + color: MyColors.lightTextColor, + fontSize: 12, + isBold: true) + .paddingOnly(bottom: 2), ], ) ], @@ -250,13 +333,21 @@ class ReviewAppointment extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - "Total Amount ".toText(fontSize: 18, isBold: true), + LocaleKeys.totalAmount.tr().toText(fontSize: 18, isBold: true), Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - appointmentsVM.totalAmount.toString().toText(fontSize: 29, isBold: true), + appointmentsVM.totalAmount + .toString() + .toText(fontSize: 29, isBold: true), 2.width, - "SAR".toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5), + LocaleKeys.sar + .tr() + .toText( + color: MyColors.lightTextColor, + fontSize: 16, + isBold: true) + .paddingOnly(bottom: 5), ], ) ], @@ -267,7 +358,7 @@ class ReviewAppointment extends StatelessWidget { child: ShowFillButton( maxHeight: 55, backgroundColor: MyColors.darkPrimaryColor, - title: "Book Appointment", + title: LocaleKeys.bookAppointment.tr(), onPressed: () { appointmentsVM.onBookAppointmentPressed(context); }, @@ -282,7 +373,7 @@ class ReviewAppointment extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: "Review Appointment", + title: LocaleKeys.reviewAppointment.tr(), isRemoveBackButton: false, isDrawerEnabled: false, onBackButtonTapped: () => Navigator.pop(context), diff --git a/lib/views/branches/branches_filter_view.dart b/lib/views/branches/branches_filter_view.dart index 9adbc7d..9f99c55 100644 --- a/lib/views/branches/branches_filter_view.dart +++ b/lib/views/branches/branches_filter_view.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart'; @@ -15,6 +16,7 @@ import 'package:mc_common_app/widgets/common_widgets/slider_widget.dart'; import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; class BranchesFilterView extends StatefulWidget { const BranchesFilterView({super.key}); @@ -45,7 +47,7 @@ class _BranchesFilterViewState extends State { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: "Branches Filter", + title: LocaleKeys.branchesFilter.tr(), profileImageUrl: MyAssets.bnCar, isRemoveBackButton: false, isDrawerEnabled: false, @@ -55,7 +57,8 @@ class _BranchesFilterViewState extends State { }, ), body: Consumer( - builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) { + builder: (BuildContext context, AppointmentsVM appointmentsVM, + Widget? child) { return WillPopScope( onWillPop: () async { context.read().resetValues(); @@ -67,31 +70,55 @@ class _BranchesFilterViewState extends State { children: [ 20.height, SearchEntityWidget( - title: "Search By Provider", + title: LocaleKeys.searchByProvider.tr(), actionWidget: Builder( builder: (context) { return DropdownField( - (DropValue value) => appointmentsVM.updateBranchFilterSelectedProviderId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + (DropValue value) => appointmentsVM + .updateBranchFilterSelectedProviderId( + SelectionModel( + selectedId: value.id, + selectedOption: value.value), + isForSearch: true), list: appointmentsVM.providersDropList, - dropdownValue: appointmentsVM.branchFilterSelectedProviderId.selectedId != -1 - ? DropValue(appointmentsVM.branchFilterSelectedProviderId.selectedId, appointmentsVM.branchFilterSelectedProviderId.selectedOption, "") + dropdownValue: appointmentsVM + .branchFilterSelectedProviderId + .selectedId != + -1 + ? DropValue( + appointmentsVM + .branchFilterSelectedProviderId + .selectedId, + appointmentsVM + .branchFilterSelectedProviderId + .selectedOption, + "") : null, - hint: "Select Provider", + hint: LocaleKeys.selectProvider.tr(), ); }, ), - historyContent: appointmentsVM.branchFilterProviderSearchHistory, + historyContent: + appointmentsVM.branchFilterProviderSearchHistory, onHistoryItemDeleted: (index) { - appointmentsVM.removeBranchFilterProviderSearchHistory(index: index); + appointmentsVM.removeBranchFilterProviderSearchHistory( + index: index); }, onHistoryItemTapped: (DropValue value) => - appointmentsVM.updateBranchFilterSelectedProviderId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + appointmentsVM.updateBranchFilterSelectedProviderId( + SelectionModel( + selectedId: value.id, + selectedOption: value.value), + isForSearch: true), ), - const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), + const Divider(thickness: 1.2) + .paddingOnly(top: 5, bottom: 5), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Search By Distance".toText(fontSize: 16, isBold: true), + LocaleKeys.searchByDistance + .tr() + .toText(fontSize: 16, isBold: true), Row( children: [ "0 KM".toText(fontSize: 12, isBold: true), @@ -99,59 +126,104 @@ class _BranchesFilterViewState extends State { child: SliderWidget( minValue: 0, maxValue: 100, - value: appointmentsVM.branchFilterCurrentDistance, - onChanged: appointmentsVM.updateBranchFilterCurrentDistance, + value: + appointmentsVM.branchFilterCurrentDistance, + onChanged: appointmentsVM + .updateBranchFilterCurrentDistance, ), ), - "${appointmentsVM.branchFilterCurrentDistance.toInt()} KM".toText(fontSize: 12, isBold: true), + "${appointmentsVM.branchFilterCurrentDistance.toInt()} KM" + .toText(fontSize: 12, isBold: true), ], ), ], ), - const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), + const Divider(thickness: 1.2) + .paddingOnly(top: 5, bottom: 5), SearchEntityWidget( - title: "Search By Category", + title: LocaleKeys.searchByCategory.tr(), actionWidget: Builder( builder: (context) { return DropdownField( - (DropValue value) => appointmentsVM.updateBranchFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + (DropValue value) => appointmentsVM + .updateBranchFilterSelectedCategoryId( + SelectionModel( + selectedId: value.id, + selectedOption: value.value), + isForSearch: true), list: appointmentsVM.categoryDropList, - dropdownValue: appointmentsVM.branchFilterSelectedCategoryId.selectedId != -1 - ? DropValue(appointmentsVM.branchFilterSelectedCategoryId.selectedId, appointmentsVM.branchFilterSelectedCategoryId.selectedOption, "") + dropdownValue: appointmentsVM + .branchFilterSelectedCategoryId + .selectedId != + -1 + ? DropValue( + appointmentsVM + .branchFilterSelectedCategoryId + .selectedId, + appointmentsVM + .branchFilterSelectedCategoryId + .selectedOption, + "") : null, - hint: "Select Category", + hint: LocaleKeys.selectCategory.tr(), ); }, ), - historyContent: appointmentsVM.branchFilterCategorySearchHistory, + historyContent: + appointmentsVM.branchFilterCategorySearchHistory, onHistoryItemDeleted: (index) { - appointmentsVM.removeBranchFilterCategorySearchHistory(index: index); + appointmentsVM.removeBranchFilterCategorySearchHistory( + index: index); }, onHistoryItemTapped: (DropValue value) => - appointmentsVM.updateBranchFilterSelectedCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + appointmentsVM.updateBranchFilterSelectedCategoryId( + SelectionModel( + selectedId: value.id, + selectedOption: value.value), + isForSearch: true), ), - const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), + const Divider(thickness: 1.2) + .paddingOnly(top: 5, bottom: 5), SearchEntityWidget( - title: "Search By Service", + title: LocaleKeys.searchByService.tr(), actionWidget: Builder(builder: (context) { return DropdownField( - (DropValue value) => appointmentsVM.updateBranchFilterSelectedServiceId(SelectionModel(selectedId: value.id, selectedOption: value.value), isForSearch: true), + (DropValue value) => appointmentsVM + .updateBranchFilterSelectedServiceId( + SelectionModel( + selectedId: value.id, + selectedOption: value.value), + isForSearch: true), list: appointmentsVM.servicesDropList, - dropdownValue: appointmentsVM.branchFilterSelectedServiceId.selectedId != -1 - ? DropValue(appointmentsVM.branchFilterSelectedServiceId.selectedId, appointmentsVM.branchFilterSelectedServiceId.selectedOption, "") + dropdownValue: appointmentsVM + .branchFilterSelectedServiceId + .selectedId != + -1 + ? DropValue( + appointmentsVM + .branchFilterSelectedServiceId.selectedId, + appointmentsVM.branchFilterSelectedServiceId + .selectedOption, + "") : null, - hint: "Select Services", + hint: LocaleKeys.selectService.tr(), ); }), - historyContent: appointmentsVM.branchFilterServicesSearchHistory, - onHistoryItemDeleted: (index) => appointmentsVM.removeBranchFilterServicesSearchHistory(index: index), + historyContent: + appointmentsVM.branchFilterServicesSearchHistory, + onHistoryItemDeleted: (index) => appointmentsVM + .removeBranchFilterServicesSearchHistory( + index: index), onHistoryItemTapped: (DropValue value) => null, ), - const Divider(thickness: 1.2).paddingOnly(top: 5, bottom: 5), + const Divider(thickness: 1.2) + .paddingOnly(top: 5, bottom: 5), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Search By Minimum Ratings".toText(fontSize: 16, isBold: true), + LocaleKeys.searchByMinimumRatings + .tr() + .toText(fontSize: 16, isBold: true), Row( children: [ "1 Star".toText(fontSize: 12, isBold: true), @@ -160,10 +232,12 @@ class _BranchesFilterViewState extends State { minValue: 0, maxValue: 5, value: appointmentsVM.branchFilterByRating, - onChanged: appointmentsVM.updateBranchFilterByRating, + onChanged: + appointmentsVM.updateBranchFilterByRating, ), ), - "${appointmentsVM.branchFilterByRating.toInt()} Star".toText(fontSize: 12, isBold: true), + "${appointmentsVM.branchFilterByRating.toInt()} Star" + .toText(fontSize: 12, isBold: true), ], ), ], @@ -180,7 +254,7 @@ class _BranchesFilterViewState extends State { Expanded( child: ShowFillButton( maxHeight: 55, - title: "Search", + title: LocaleKeys.search.tr(), onPressed: () { Navigator.pop(context); appointmentsVM.getBranchesBasedOnFilters(); @@ -195,11 +269,11 @@ class _BranchesFilterViewState extends State { 8.height, InkWell( onTap: () => appointmentsVM.clearBranchFilters(), - child: "Clear Filters".toText( - fontSize: 14, - isBold: true, - color: MyColors.darkPrimaryColor, - ), + child: LocaleKeys.clearFilters.tr().toText( + fontSize: 14, + isBold: true, + color: MyColors.darkPrimaryColor, + ), ), 10.height, ], diff --git a/lib/views/chat/chat_view.dart b/lib/views/chat/chat_view.dart index 45e9de4..044daa9 100644 --- a/lib/views/chat/chat_view.dart +++ b/lib/views/chat/chat_view.dart @@ -6,6 +6,7 @@ import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/chat_models/chat_message_model.dart'; import 'package:mc_common_app/models/requests_models/request_model.dart'; import 'package:mc_common_app/theme/colors.dart'; @@ -19,6 +20,7 @@ import 'package:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/txt_field.dart'; import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart' as lcl; class ChatView extends StatelessWidget { final ChatViewArguments chatViewArguments; @@ -32,11 +34,15 @@ class ChatView extends StatelessWidget { isScrollControlled: true, enableDrag: true, builder: (BuildContext context) { - return Consumer(builder: (BuildContext context, RequestsVM requestsVM, Widget? child) { + return Consumer(builder: + (BuildContext context, RequestsVM requestsVM, Widget? child) { return InfoBottomSheet( - title: "Make an offer".toText(fontSize: 28, isBold: true, letterSpacing: -1.44), + title: LocaleKeys.makeAnOffer + .tr() + .toText(fontSize: 28, isBold: true, letterSpacing: -1.44), description: Padding( - padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + padding: EdgeInsets.only( + bottom: MediaQuery.of(context).viewInsets.bottom), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -48,7 +54,7 @@ class ChatView extends StatelessWidget { value: requestsVM.offerPrice, errorValue: requestsVM.offerPriceError, keyboardType: TextInputType.number, - hint: "Enter amount", + hint: LocaleKeys.enterAmount.tr(), onChanged: (v) => requestsVM.updateOfferPrice(v), ), 12.height, @@ -57,14 +63,15 @@ class ChatView extends StatelessWidget { value: requestsVM.offerDescription, errorValue: requestsVM.offerDescriptionError, keyboardType: TextInputType.text, - hint: "Description", - onChanged: (v) => requestsVM.updateOfferDescription(v), + hint: LocaleKeys.description.tr(), + onChanged: (v) => + requestsVM.updateOfferDescription(v), ), ], ), 25.height, ShowFillButton( - title: "Submit", + title: LocaleKeys.submit.tr(), onPressed: () { requestsVM.onSendOfferPressed( context: context, @@ -91,22 +98,30 @@ class ChatView extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: const CustomAppBar(title: "Chat"), - body: Consumer2(builder: (BuildContext context, ChatVM chatVM, RequestsVM requestVM, Widget? child) { + appBar: CustomAppBar(title: LocaleKeys.chat.tr()), + body: Consumer2(builder: (BuildContext context, + ChatVM chatVM, RequestsVM requestVM, Widget? child) { final chatMessages = AppState().currentAppType == AppType.customer - ? chatVM.serviceProviderOffersList[chatViewArguments.providerIndex].chatMessages - : requestVM.myFilteredRequests[chatViewArguments.requestIndex].chatMessages; + ? chatVM.serviceProviderOffersList[chatViewArguments.providerIndex] + .chatMessages + : requestVM.myFilteredRequests[chatViewArguments.requestIndex] + .chatMessages; return chatMessages == null - ? Center(child: "No Requests to show.".toText(fontSize: 16, color: MyColors.lightTextColor)) + ? Center( + child: LocaleKeys.noRequestsShow + .tr() + .toText(fontSize: 16, color: MyColors.lightTextColor)) : Column( children: [ Expanded( child: ListView.separated( itemCount: chatMessages.length, - separatorBuilder: (BuildContext context, int index) => 20.height, + separatorBuilder: (BuildContext context, int index) => + 20.height, itemBuilder: (BuildContext context, int index) { ChatMessageModel chatMessageModel = chatMessages[index]; - return ChatMessageCustomWidget(chatMessageModel: chatMessageModel); + return ChatMessageCustomWidget( + chatMessageModel: chatMessageModel); }, ).horPaddingMain(), ), @@ -132,7 +147,7 @@ class ChatView extends StatelessWidget { flex: 8, child: TxtField( value: chatVM.chatMessageText, - hint: "Type your message here..", + hint: LocaleKeys.typeMessageHere.tr(), keyboardType: TextInputType.text, isNeedBorder: false, onChanged: (v) => chatVM.updateChatMessageText(v), @@ -178,7 +193,8 @@ class ChatMessageCustomWidget extends StatefulWidget { const ChatMessageCustomWidget({super.key, required this.chatMessageModel}); @override - State createState() => _ChatMessageCustomWidgetState(); + State createState() => + _ChatMessageCustomWidgetState(); } class _ChatMessageCustomWidgetState extends State { @@ -188,11 +204,15 @@ class _ChatMessageCustomWidgetState extends State { isScrollControlled: true, enableDrag: true, builder: (BuildContext context) { - return Consumer(builder: (BuildContext context, ChatVM chatVM, Widget? child) { + return Consumer( + builder: (BuildContext context, ChatVM chatVM, Widget? child) { return InfoBottomSheet( - title: "Make an offer".toText(fontSize: 28, isBold: true, letterSpacing: -1.44), + title: LocaleKeys.makeAnOffer + .tr() + .toText(fontSize: 28, isBold: true, letterSpacing: -1.44), description: Padding( - padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), + padding: EdgeInsets.only( + bottom: MediaQuery.of(context).viewInsets.bottom), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -203,14 +223,18 @@ class _ChatMessageCustomWidgetState extends State { ListView.separated( shrinkWrap: true, itemCount: chatVM.offerRejectModelList.length, - separatorBuilder: (BuildContext context, int index) => const Divider(thickness: 0.5), + separatorBuilder: (BuildContext context, int index) => + const Divider(thickness: 0.5), itemBuilder: (BuildContext context, int index) { - OfferRequestCommentModel offerRequestCommentModel = chatVM.offerRejectModelList[index]; + OfferRequestCommentModel offerRequestCommentModel = + chatVM.offerRejectModelList[index]; return CircleCheckBoxWithTitle( - isChecked: offerRequestCommentModel.isSelected ?? false, + isChecked: + offerRequestCommentModel.isSelected ?? false, title: '${offerRequestCommentModel.title}', onSelected: () { - chatVM.updateSelectionInOfferRejectModelList(index); + chatVM.updateSelectionInOfferRejectModelList( + index); }, selectedColor: MyColors.darkPrimaryColor, ); @@ -222,14 +246,15 @@ class _ChatMessageCustomWidgetState extends State { value: chatVM.rejectOfferDescription, errorValue: chatVM.rejectOfferDescriptionError, keyboardType: TextInputType.text, - hint: "Description", - onChanged: (v) => chatVM.updateRejectOfferDescription(v), + hint: LocaleKeys.description.tr(), + onChanged: (v) => + chatVM.updateRejectOfferDescription(v), ), ], ), 25.height, ShowFillButton( - title: "Submit", + title: LocaleKeys.submit.tr(), onPressed: () {}, maxWidth: double.infinity, ), @@ -242,8 +267,12 @@ class _ChatMessageCustomWidgetState extends State { ); } - Widget buildOfferDetailsInChatMessage({required ChatMessageModel chatMessageModel, required BuildContext context}) { - final requestOfferStatusEnum = chatMessageModel.reqOffer!.requestOfferStatusEnum ?? RequestOfferStatusEnum.offer; + Widget buildOfferDetailsInChatMessage( + {required ChatMessageModel chatMessageModel, + required BuildContext context}) { + final requestOfferStatusEnum = + chatMessageModel.reqOffer!.requestOfferStatusEnum ?? + RequestOfferStatusEnum.offer; switch (requestOfferStatusEnum) { case RequestOfferStatusEnum.offer: @@ -253,9 +282,18 @@ class _ChatMessageCustomWidgetState extends State { Row( crossAxisAlignment: CrossAxisAlignment.end, children: [ - "${chatMessageModel.reqOffer!.price}".toText(fontSize: 19, isBold: true, color: AppState().currentAppType == AppType.provider ? MyColors.white : MyColors.darkTextColor), + "${chatMessageModel.reqOffer!.price}".toText( + fontSize: 19, + isBold: true, + color: AppState().currentAppType == AppType.provider + ? MyColors.white + : MyColors.darkTextColor), 5.width, - "SAR".toText(color: MyColors.lightTextColor, height: 2.2, fontSize: 10, isBold: true), + LocaleKeys.sar.tr().toText( + color: MyColors.lightTextColor, + height: 2.2, + fontSize: 10, + isBold: true), ], ), if (widget.chatMessageModel.isMyMessage == false) ...[ @@ -265,21 +303,24 @@ class _ChatMessageCustomWidgetState extends State { Expanded( child: ShowFillButton( maxHeight: 27, - title: "Accept", + title: LocaleKeys.accept.tr(), fontSize: 9, borderColor: MyColors.greenColor, isFilled: false, onPressed: () async { - int status = await context.read().onActionOfferTapped( - context: context, - requestOfferStatusEnum: RequestOfferStatusEnum.accepted, - reqOfferId: chatMessageModel.reqOfferID ?? -1, - ); + int status = + await context.read().onActionOfferTapped( + context: context, + requestOfferStatusEnum: + RequestOfferStatusEnum.accepted, + reqOfferId: chatMessageModel.reqOfferID ?? -1, + ); if (status != -1) { log("accepted: $status"); if (chatMessageModel.reqOfferID == status) { - chatMessageModel.reqOffer!.requestOfferStatusEnum = RequestOfferStatusEnum.accepted; + chatMessageModel.reqOffer!.requestOfferStatusEnum = + RequestOfferStatusEnum.accepted; setState(() {}); } } @@ -292,7 +333,7 @@ class _ChatMessageCustomWidgetState extends State { Expanded( child: ShowFillButton( maxHeight: 27, - title: "Reject", + title: LocaleKeys.reject.tr(), borderColor: MyColors.redColor, isFilled: false, backgroundColor: MyColors.white, @@ -312,48 +353,64 @@ class _ChatMessageCustomWidgetState extends State { return Column( children: [ Center( - child: "New Offer Required.".toText( - color: MyColors.adPendingStatusColor, - fontSize: 12, - isItalic: true, - ), - ).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)), + child: LocaleKeys.newOfferRequired.tr().toText( + color: MyColors.adPendingStatusColor, + fontSize: 12, + isItalic: true, + ), + ).toContainer( + borderRadius: 40, + width: double.infinity, + backgroundColor: + MyColors.adPendingStatusColor.withOpacity(0.16)), ], ); case RequestOfferStatusEnum.accepted: return Column( children: [ Center( - child: "Offer has been accepted.".toText( - color: MyColors.adPendingStatusColor, - fontSize: 12, - isItalic: true, - ), - ).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)), + child: LocaleKeys.offerHasBeenAccepted.tr().toText( + color: MyColors.adPendingStatusColor, + fontSize: 12, + isItalic: true, + ), + ).toContainer( + borderRadius: 40, + width: double.infinity, + backgroundColor: + MyColors.adPendingStatusColor.withOpacity(0.16)), ], ); case RequestOfferStatusEnum.rejected: return Column( children: [ Center( - child: "Offer has been rejected.".toText( - color: MyColors.adPendingStatusColor, - fontSize: 12, - isItalic: true, - ), - ).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)), + child: LocaleKeys.offerHasBeenRejected.tr().toText( + color: MyColors.adPendingStatusColor, + fontSize: 12, + isItalic: true, + ), + ).toContainer( + borderRadius: 40, + width: double.infinity, + backgroundColor: + MyColors.adPendingStatusColor.withOpacity(0.16)), ], ); case RequestOfferStatusEnum.cancel: return Column( children: [ Center( - child: "Offer has been cancelled.".toText( - color: MyColors.adPendingStatusColor, - fontSize: 12, - isItalic: true, - ), - ).toContainer(borderRadius: 40, width: double.infinity, backgroundColor: MyColors.adPendingStatusColor.withOpacity(0.16)), + child: LocaleKeys.offerHasBeenCancelled.tr().toText( + color: MyColors.adPendingStatusColor, + fontSize: 12, + isItalic: true, + ), + ).toContainer( + borderRadius: 40, + width: double.infinity, + backgroundColor: + MyColors.adPendingStatusColor.withOpacity(0.16)), ], ); } @@ -362,7 +419,9 @@ class _ChatMessageCustomWidgetState extends State { @override Widget build(BuildContext context) { return Directionality( - textDirection: (widget.chatMessageModel.isMyMessage ?? false) ? TextDirection.rtl : TextDirection.ltr, + textDirection: (widget.chatMessageModel.isMyMessage ?? false) + ? TextDirection.rtl + : TextDirection.ltr, child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -384,7 +443,10 @@ class _ChatMessageCustomWidgetState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - ((widget.chatMessageModel.isMyMessage ?? false) ? "You" : widget.chatMessageModel.senderName ?? "").toText(fontSize: 16, isBold: true), + ((widget.chatMessageModel.isMyMessage ?? false) + ? "You" + : widget.chatMessageModel.senderName ?? "") + .toText(fontSize: 16, isBold: true), ], ), 5.height, @@ -396,8 +458,12 @@ class _ChatMessageCustomWidgetState extends State { Expanded( child: Directionality( textDirection: TextDirection.ltr, - child: (widget.chatMessageModel.chatText ?? "").toText( - color: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.white : MyColors.lightTextColor, + child: + (widget.chatMessageModel.chatText ?? "").toText( + color: + (widget.chatMessageModel.isMyMessage ?? false) + ? MyColors.white + : MyColors.lightTextColor, fontSize: 12, // isBold: true, @@ -406,15 +472,26 @@ class _ChatMessageCustomWidgetState extends State { ), ], ), - if (widget.chatMessageModel.chatMessageTypeEnum == ChatMessageTypeEnum.offer) ...[ - buildOfferDetailsInChatMessage(chatMessageModel: widget.chatMessageModel, context: context), + if (widget.chatMessageModel.chatMessageTypeEnum == + ChatMessageTypeEnum.offer) ...[ + buildOfferDetailsInChatMessage( + chatMessageModel: widget.chatMessageModel, + context: context), ], ], ).toContainer( - isShadowEnabled: !(widget.chatMessageModel.isMyMessage ?? false), - backgroundColor: (widget.chatMessageModel.isMyMessage ?? false) ? MyColors.darkIconColor : MyColors.white, + isShadowEnabled: + !(widget.chatMessageModel.isMyMessage ?? false), + backgroundColor: + (widget.chatMessageModel.isMyMessage ?? false) + ? MyColors.darkIconColor + : MyColors.white, borderRadius: 0, - margin: EdgeInsets.fromLTRB((widget.chatMessageModel.isMyMessage ?? false) ? 25 : 0, 0, !(widget.chatMessageModel.isMyMessage ?? false) ? 25 : 0, 0), + margin: EdgeInsets.fromLTRB( + (widget.chatMessageModel.isMyMessage ?? false) ? 25 : 0, + 0, + !(widget.chatMessageModel.isMyMessage ?? false) ? 25 : 0, + 0), ), ], ), diff --git a/lib/views/payments/payment_methods_view.dart b/lib/views/payments/payment_methods_view.dart index 95215c1..08d3bf1 100644 --- a/lib/views/payments/payment_methods_view.dart +++ b/lib/views/payments/payment_methods_view.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/utils.dart'; @@ -9,6 +10,7 @@ import 'package:mc_common_app/view_models/payment_view_model.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; class PaymentMethodsView extends StatelessWidget { final PaymentTypes paymentType; @@ -22,7 +24,7 @@ class PaymentMethodsView extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: "Payment Method", + title: LocaleKeys.paymentMethod.tr(), profileImageUrl: MyAssets.bnCar, isRemoveBackButton: false, isDrawerEnabled: false, @@ -34,33 +36,46 @@ class PaymentMethodsView extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ 20.height, - "Select Payment Method".toText(fontSize: 18, isBold: true), + LocaleKeys.selectPaymentMethod + .tr() + .toText(fontSize: 18, isBold: true), 15.height, Consumer( - builder: (BuildContext context, PaymentVM paymentVm, Widget? child) { + builder: + (BuildContext context, PaymentVM paymentVm, Widget? child) { return Expanded( child: ListView( shrinkWrap: true, children: [ PaymentMethodContainer( - isSelected: paymentVm.selectedPaymentMethod == PaymentMethods.mada, - onTap: () => paymentVm.updateSelectedPaymentMethod(PaymentMethods.mada), + isSelected: paymentVm.selectedPaymentMethod == + PaymentMethods.mada, + onTap: () => paymentVm + .updateSelectedPaymentMethod(PaymentMethods.mada), cardAsset: MyAssets.madaPng), PaymentMethodContainer( - isSelected: paymentVm.selectedPaymentMethod == PaymentMethods.visa, - onTap: () => paymentVm.updateSelectedPaymentMethod(PaymentMethods.visa), + isSelected: paymentVm.selectedPaymentMethod == + PaymentMethods.visa, + onTap: () => paymentVm + .updateSelectedPaymentMethod(PaymentMethods.visa), cardAsset: MyAssets.visaPng), PaymentMethodContainer( - isSelected: paymentVm.selectedPaymentMethod == PaymentMethods.applePay, - onTap: () => paymentVm.updateSelectedPaymentMethod(PaymentMethods.applePay), + isSelected: paymentVm.selectedPaymentMethod == + PaymentMethods.applePay, + onTap: () => paymentVm.updateSelectedPaymentMethod( + PaymentMethods.applePay), cardAsset: MyAssets.applePayPng), PaymentMethodContainer( - isSelected: paymentVm.selectedPaymentMethod == PaymentMethods.masterCard, - onTap: () => paymentVm.updateSelectedPaymentMethod(PaymentMethods.masterCard), + isSelected: paymentVm.selectedPaymentMethod == + PaymentMethods.masterCard, + onTap: () => paymentVm.updateSelectedPaymentMethod( + PaymentMethods.masterCard), cardAsset: MyAssets.mastercardPng), PaymentMethodContainer( - isSelected: paymentVm.selectedPaymentMethod == PaymentMethods.tamara, - onTap: () => paymentVm.updateSelectedPaymentMethod(PaymentMethods.tamara), + isSelected: paymentVm.selectedPaymentMethod == + PaymentMethods.tamara, + onTap: () => paymentVm.updateSelectedPaymentMethod( + PaymentMethods.tamara), cardAsset: MyAssets.tamaraEngPng), ], ), @@ -71,7 +86,7 @@ class PaymentMethodsView extends StatelessWidget { width: double.infinity, child: ShowFillButton( maxHeight: 55, - title: "Continue", + title: LocaleKeys.continu.tr(), onPressed: () async { bool isNeedToCallPayment = true; if (onTempContinue != null) { @@ -99,7 +114,12 @@ class PaymentMethodContainer extends StatelessWidget { final String cardAsset; final Function() onTap; - const PaymentMethodContainer({Key? key, required this.isSelected, required this.cardAsset, required this.onTap}) : super(key: key); + const PaymentMethodContainer( + {Key? key, + required this.isSelected, + required this.cardAsset, + required this.onTap}) + : super(key: key); @override Widget build(BuildContext context) { @@ -112,7 +132,9 @@ class PaymentMethodContainer extends StatelessWidget { decoration: BoxDecoration( color: MyColors.white, borderRadius: BorderRadius.circular(10), - border: Border.all(color: isSelected ? Colors.green : Colors.transparent, width: isSelected ? 2.0 : 0.0), + border: Border.all( + color: isSelected ? Colors.green : Colors.transparent, + width: isSelected ? 2.0 : 0.0), ), child: Padding( padding: const EdgeInsets.all(12), @@ -121,7 +143,11 @@ class PaymentMethodContainer extends StatelessWidget { Container( width: 24, height: 24, - decoration: Utils.containerColorRadiusBorderWidth(isSelected ? MyColors.primaryColor : Colors.transparent, 100, Colors.grey, 0.5), + decoration: Utils.containerColorRadiusBorderWidth( + isSelected ? MyColors.primaryColor : Colors.transparent, + 100, + Colors.grey, + 0.5), ), 12.width, Container( @@ -131,7 +157,12 @@ class PaymentMethodContainer extends StatelessWidget { child: Image.asset(cardAsset), ), Utils.mFlex(1), - isSelected ? Utils.statusContainerChip(text: "Selected", padding: EdgeInsets.symmetric(vertical: 6, horizontal: 10)) : SizedBox(), + isSelected + ? Utils.statusContainerChip( + text: "Selected", + padding: + EdgeInsets.symmetric(vertical: 6, horizontal: 10)) + : SizedBox(), ], ), ), diff --git a/lib/views/profile/profile_view.dart b/lib/views/profile/profile_view.dart index 4f27aba..5de4917 100644 --- a/lib/views/profile/profile_view.dart +++ b/lib/views/profile/profile_view.dart @@ -9,6 +9,7 @@ import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/app_permission_handler.dart'; import 'package:mc_common_app/view_models/service_view_model.dart'; @@ -19,6 +20,7 @@ import 'package:mc_common_app/views/user/change_password_page.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; class ProfileScreen extends StatefulWidget { const ProfileScreen({Key? key}) : super(key: key); @@ -52,15 +54,29 @@ class _ProfileScreenState extends State { flex: 3, child: Container( decoration: BoxDecoration( - image: AppState().getUser.data!.userInfo!.userLocalImage != null + image: AppState() + .getUser + .data! + .userInfo! + .userLocalImage != + null ? DecorationImage( - image: FileImage(AppState().getUser.data!.userInfo!.userLocalImage!), + image: FileImage(AppState() + .getUser + .data! + .userInfo! + .userLocalImage!), fit: BoxFit.cover, ) - : AppState().getUser.data!.userInfo!.userImageUrl != null + : AppState().getUser.data!.userInfo!.userImageUrl != + null ? DecorationImage( image: CachedNetworkImageProvider( - AppState().getUser.data!.userInfo!.userImageUrl, + AppState() + .getUser + .data! + .userInfo! + .userImageUrl, ), fit: BoxFit.cover, ) @@ -87,40 +103,52 @@ class _ProfileScreenState extends State { child: ListView( children: [ 20.height, - "${AppState().getUser.data!.userInfo!.firstName} ${AppState().getUser.data!.userInfo!.lastName ?? ""}".toText(fontSize: 20).paddingOnly(left: 25), + "${AppState().getUser.data!.userInfo!.firstName} ${AppState().getUser.data!.userInfo!.lastName ?? ""}" + .toText(fontSize: 20) + .paddingOnly(left: 25), Column( children: [ CustomProfileOptionsTile( - titleText: "Country", + titleText: LocaleKeys.country.tr(), subtitleText: "Saudi Arabia", needBorderBelow: true, onTap: () {}, ), CustomProfileOptionsTile( - titleText: "Email", - subtitleText: "${AppState().getUser.data!.userInfo!.email}", + titleText: LocaleKeys.email.tr(), + subtitleText: + "${AppState().getUser.data!.userInfo!.email}", needBorderBelow: true, onTap: () { - Navigator.pushNamed(context, AppRoutes.changeEmailPage); + Navigator.pushNamed( + context, AppRoutes.changeEmailPage); }, ), CustomProfileOptionsTile( - titleText: "Phone Number", - subtitleText: "${AppState().getUser.data!.userInfo!.email}", + titleText: LocaleKeys.phoneNumber.tr(), + subtitleText: + "${AppState().getUser.data!.userInfo!.email}", needBorderBelow: true, onTap: () { - Navigator.pushNamed(context, AppRoutes.changeMobilePage); + Navigator.pushNamed( + context, AppRoutes.changeMobilePage); }, ), CustomProfileOptionsTile( - titleText: "Password", + titleText: LocaleKeys.password.tr(), subtitleText: "************", onTap: () { - Navigator.pushNamed(context, AppRoutes.changePassword); + Navigator.pushNamed( + context, AppRoutes.changePassword); }, ), ], - ).toContainer(width: double.infinity, isShadowEnabled: true, paddingAll: 10, margin: const EdgeInsets.fromLTRB(24, 20, 24, 0), borderRadius: 0), + ).toContainer( + width: double.infinity, + isShadowEnabled: true, + paddingAll: 10, + margin: const EdgeInsets.fromLTRB(24, 20, 24, 0), + borderRadius: 0), ], ), ), @@ -133,7 +161,8 @@ class _ProfileScreenState extends State { height: 90, alignment: Alignment.centerLeft, child: ClipOval( - child: AppState().getUser.data!.userInfo!.userLocalImage != null + child: AppState().getUser.data!.userInfo!.userLocalImage != + null ? Image.file( AppState().getUser.data!.userInfo!.userLocalImage!, width: 90, @@ -141,7 +170,8 @@ class _ProfileScreenState extends State { fit: BoxFit.fill, ) : CachedNetworkImage( - imageUrl: "${AppState().getUser.data!.userInfo!.userImageUrl}", + imageUrl: + "${AppState().getUser.data!.userInfo!.userImageUrl}", imageBuilder: (context, imageProvider) => Container( decoration: BoxDecoration( image: DecorationImage( @@ -150,8 +180,10 @@ class _ProfileScreenState extends State { ), ), ), - placeholder: (context, url) => const Center(child: CircularProgressIndicator()), - errorWidget: (context, url, error) => const Icon(Icons.error), + placeholder: (context, url) => + const Center(child: CircularProgressIndicator()), + errorWidget: (context, url, error) => + const Icon(Icons.error), width: 90, height: 90, fit: BoxFit.fill, @@ -168,8 +200,14 @@ class _ProfileScreenState extends State { child: Container( height: 35, width: 35, - decoration: BoxDecoration(color: MyColors.white, shape: BoxShape.circle, border: Border.all(color: MyColors.darkTextColor, width: 0.1)), - child: const Icon(Icons.edit_note, color: MyColors.darkIconColor, size: 27).paddingOnly(left: 5), + decoration: BoxDecoration( + color: MyColors.white, + shape: BoxShape.circle, + border: + Border.all(color: MyColors.darkTextColor, width: 0.1)), + child: const Icon(Icons.edit_note, + color: MyColors.darkIconColor, size: 27) + .paddingOnly(left: 5), ).onPress( () async { model.updateUserImage(context); diff --git a/lib/views/requests/create_request_page.dart b/lib/views/requests/create_request_page.dart index 6ed828f..ef572ae 100644 --- a/lib/views/requests/create_request_page.dart +++ b/lib/views/requests/create_request_page.dart @@ -1,3 +1,4 @@ +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/view_models/requests_view_model.dart'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; @@ -13,6 +14,7 @@ import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/txt_field.dart'; import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; class CreateRequestPage extends StatelessWidget { const CreateRequestPage({super.key}); @@ -20,8 +22,8 @@ class CreateRequestPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: const CustomAppBar( - title: "Create Request", + appBar: CustomAppBar( + title: LocaleKeys.createRequest.tr(), ), body: Consumer(builder: (context, requestsVM, widget) { return Column( @@ -31,204 +33,323 @@ class CreateRequestPage extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - "Vehicle Detail".toText(fontSize: 18, isBold: true), + LocaleKeys.vehicleDetails + .tr() + .toText(fontSize: 18, isBold: true), 8.height, if (requestsVM.isFetchingRequestType) ...[ const Center( child: CircularProgressIndicator(), ), - ] else - ...[ - Builder(builder: (context) { - List requestTypeDrop = []; - for (var element in requestsVM.myRequestsTypeEnum) { - requestTypeDrop.add(DropValue(element.enumValue.toInt() ?? 0, element.enumValueStr ?? "", "")); - } - return DropdownField( - (DropValue value) => requestsVM.updateSelectionRequestTypeId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: requestTypeDrop, - dropdownValue: requestsVM.requestTypeId.selectedId != -1 ? DropValue(requestsVM.requestTypeId.selectedId, requestsVM.requestTypeId.selectedOption, "") : null, - hint: "Request Type", - errorValue: requestsVM.requestTypeId.errorValue, - ); - }), - ], + ] else ...[ + Builder(builder: (context) { + List requestTypeDrop = []; + for (var element in requestsVM.myRequestsTypeEnum) { + requestTypeDrop.add(DropValue( + element.enumValue.toInt() ?? 0, + element.enumValueStr ?? "", + "")); + } + return DropdownField( + (DropValue value) => requestsVM + .updateSelectionRequestTypeId(SelectionModel( + selectedId: value.id, + selectedOption: value.value)), + list: requestTypeDrop, + dropdownValue: + requestsVM.requestTypeId.selectedId != -1 + ? DropValue( + requestsVM.requestTypeId.selectedId, + requestsVM.requestTypeId.selectedOption, + "") + : null, + hint: LocaleKeys.requestType.tr(), + errorValue: requestsVM.requestTypeId.errorValue, + ); + }), + ], 8.height, if (requestsVM.requestTypeId.selectedId != -1) if (requestsVM.isFetchingVehicleType) ...[ const Center( child: CircularProgressIndicator(), ), - ] else - ...[ - Builder(builder: (context) { - List vehicleTypeDrop = []; - for (var element in requestsVM.vehicleTypes) { - vehicleTypeDrop.add(DropValue(element.id?.toInt() ?? 0, element.vehicleTypeName ?? "", "")); - } - return DropdownField( - (DropValue value) => requestsVM.updateSelectionVehicleTypeId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleTypeDrop, - dropdownValue: requestsVM.vehicleTypeId.selectedId != -1 ? DropValue(requestsVM.vehicleTypeId.selectedId, requestsVM.vehicleTypeId.selectedOption, "") : null, - hint: "Vehicle Type", - errorValue: requestsVM.vehicleTypeId.errorValue, - ); - }), - ], + ] else ...[ + Builder(builder: (context) { + List vehicleTypeDrop = []; + for (var element in requestsVM.vehicleTypes) { + vehicleTypeDrop.add(DropValue( + element.id?.toInt() ?? 0, + element.vehicleTypeName ?? "", + "")); + } + return DropdownField( + (DropValue value) => requestsVM + .updateSelectionVehicleTypeId(SelectionModel( + selectedId: value.id, + selectedOption: value.value)), + list: vehicleTypeDrop, + dropdownValue: + requestsVM.vehicleTypeId.selectedId != -1 + ? DropValue( + requestsVM.vehicleTypeId.selectedId, + requestsVM.vehicleTypeId.selectedOption, + "") + : null, + hint: LocaleKeys.vehicleType.tr(), + errorValue: requestsVM.vehicleTypeId.errorValue, + ); + }), + ], 8.height, if (requestsVM.vehicleTypeId.selectedId != -1) if (requestsVM.isFetchingVehicleDetail) ...[ const Center( child: CircularProgressIndicator(), ), - ] else - ...[ - Column( - children: [ - Builder(builder: (context) { - List vehicleBrandsDrop = []; - for (var element in requestsVM.vehicleBrands) { - vehicleBrandsDrop.add(DropValue(element.id?.toInt() ?? 0, element.vehicleBrandDescription ?? "", "")); - } - return DropdownField( - (DropValue value) => requestsVM.updateSelectionVehicleBrandId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleBrandsDrop, - dropdownValue: requestsVM.vehicleBrandId.selectedId != -1 ? DropValue(requestsVM.vehicleBrandId.selectedId, requestsVM.vehicleBrandId.selectedOption, "") : null, - hint: "Brand", - errorValue: requestsVM.vehicleBrandId.errorValue, - ); - }), - 8.height, - Builder(builder: (context) { - List vehicleModelsDrop = []; - for (var element in requestsVM.vehicleModels) { - if (requestsVM.vehicleBrandId.selectedId == element.vehicleBrandID) vehicleModelsDrop.add(DropValue(element.id?.toInt() ?? 0, element.model ?? "", "")); - } - return DropdownField( - (DropValue value) => requestsVM.updateSelectionVehicleModelId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleModelsDrop, - dropdownValue: requestsVM.vehicleModelId.selectedId != -1 ? DropValue(requestsVM.vehicleModelId.selectedId, requestsVM.vehicleModelId.selectedOption, "") : null, - hint: "Model", - errorValue: requestsVM.vehicleModelId.errorValue, - ); - }), - 8.height, - Builder(builder: (context) { - List vehicleYearModelsDrop = []; - for (var element in requestsVM.vehicleModelYears) { - vehicleYearModelsDrop.add(DropValue(element.id?.toInt() ?? 0, element.modelYear ?? "", "")); - } + ] else ...[ + Column( + children: [ + Builder(builder: (context) { + List vehicleBrandsDrop = []; + for (var element in requestsVM.vehicleBrands) { + vehicleBrandsDrop.add(DropValue( + element.id?.toInt() ?? 0, + element.vehicleBrandDescription ?? "", + "")); + } + return DropdownField( + (DropValue value) => + requestsVM.updateSelectionVehicleBrandId( + SelectionModel( + selectedId: value.id, + selectedOption: value.value)), + list: vehicleBrandsDrop, + dropdownValue: + requestsVM.vehicleBrandId.selectedId != -1 + ? DropValue( + requestsVM + .vehicleBrandId.selectedId, + requestsVM + .vehicleBrandId.selectedOption, + "") + : null, + hint: LocaleKeys.brand.tr(), + errorValue: + requestsVM.vehicleBrandId.errorValue, + ); + }), + 8.height, + Builder(builder: (context) { + List vehicleModelsDrop = []; + for (var element in requestsVM.vehicleModels) { + if (requestsVM.vehicleBrandId.selectedId == + element.vehicleBrandID) + vehicleModelsDrop.add(DropValue( + element.id?.toInt() ?? 0, + element.model ?? "", + "")); + } + return DropdownField( + (DropValue value) => + requestsVM.updateSelectionVehicleModelId( + SelectionModel( + selectedId: value.id, + selectedOption: value.value)), + list: vehicleModelsDrop, + dropdownValue: + requestsVM.vehicleModelId.selectedId != -1 + ? DropValue( + requestsVM + .vehicleModelId.selectedId, + requestsVM + .vehicleModelId.selectedOption, + "") + : null, + hint: LocaleKeys.model.tr(), + errorValue: + requestsVM.vehicleModelId.errorValue, + ); + }), + 8.height, + Builder(builder: (context) { + List vehicleYearModelsDrop = []; + for (var element + in requestsVM.vehicleModelYears) { + vehicleYearModelsDrop.add(DropValue( + element.id?.toInt() ?? 0, + element.modelYear ?? "", + "")); + } - return DropdownField( - (DropValue value) => requestsVM.updateSelectionVehicleModelYearId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleYearModelsDrop, - dropdownValue: - requestsVM.vehicleModelYearId.selectedId != -1 ? DropValue(requestsVM.vehicleModelYearId.selectedId, requestsVM.vehicleModelYearId.selectedOption, "") : null, - hint: "Year", - errorValue: requestsVM.vehicleModelYearId.errorValue, - ); - }), - 8.height, - Builder(builder: (context) { - List vehicleCountriesDrop = []; - for (var element in requestsVM.vehicleCountries) { - vehicleCountriesDrop.add(DropValue(element.id?.toInt() ?? 0, element.countryName ?? "", "")); - } - return DropdownField( - (DropValue value) => requestsVM.updateSelectionVehicleCountryId(SelectionModel(selectedOption: value.value, selectedId: value.id)), - list: vehicleCountriesDrop, - dropdownValue: requestsVM.vehicleCountryId.selectedId != -1 - ? DropValue(requestsVM.vehicleCountryId.selectedId, requestsVM.vehicleCountryId.selectedOption, "") - : null, - hint: "Country", - errorValue: requestsVM.vehicleCountryId.errorValue, - ); - }), - if (requestsVM.vehicleCountryId.selectedId != -1) ...[ - if (requestsVM.isCountryFetching) ...[ - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [const CircularProgressIndicator().paddingAll(10)], - ), - ] else - ...[ - 8.height, - Builder(builder: (context) { - List vehicleCitiesDrop = []; - for (var element in requestsVM.vehicleCities) { - vehicleCitiesDrop.add(DropValue(element.id?.toInt() ?? 0, element.cityName ?? "", "")); - } - return DropdownField( - (DropValue value) => requestsVM.updateSelectionVehicleCityId(SelectionModel(selectedId: value.id, selectedOption: value.value)), - list: vehicleCitiesDrop, - dropdownValue: requestsVM.vehicleCityId.selectedId != -1 ? DropValue(requestsVM.vehicleCityId.selectedId, requestsVM.vehicleCityId.selectedOption, "") : null, - hint: "City", - errorValue: requestsVM.vehicleCityId.errorValue, - ); - }), - ], - ], - 8.height, - TxtField( - hint: "Price", - value: requestsVM.price, - keyboardType: TextInputType.number, - onChanged: (e) => requestsVM.updatePrice(e), - ), - 8.height, - TxtField( - hint: "Description", - maxLines: 5, - value: requestsVM.description, - onChanged: (e) => requestsVM.updateDescription(e), - ), - 8.height, - DottedRectContainer( - onTap: () => context.read().pickMultipleImages(), - text: "Attach Image", - icon: MyAssets.attachmentIcon.buildSvg(), - ), - if (requestsVM.vehicleImageError != "") ...[ - 10.height, + return DropdownField( + (DropValue value) => requestsVM + .updateSelectionVehicleModelYearId( + SelectionModel( + selectedId: value.id, + selectedOption: value.value)), + list: vehicleYearModelsDrop, + dropdownValue: + requestsVM.vehicleModelYearId.selectedId != + -1 + ? DropValue( + requestsVM + .vehicleModelYearId.selectedId, + requestsVM.vehicleModelYearId + .selectedOption, + "") + : null, + hint: LocaleKeys.year.tr(), + errorValue: + requestsVM.vehicleModelYearId.errorValue, + ); + }), + 8.height, + Builder(builder: (context) { + List vehicleCountriesDrop = []; + for (var element in requestsVM.vehicleCountries) { + vehicleCountriesDrop.add(DropValue( + element.id?.toInt() ?? 0, + element.countryName ?? "", + "")); + } + return DropdownField( + (DropValue value) => + requestsVM.updateSelectionVehicleCountryId( + SelectionModel( + selectedOption: value.value, + selectedId: value.id)), + list: vehicleCountriesDrop, + dropdownValue: + requestsVM.vehicleCountryId.selectedId != -1 + ? DropValue( + requestsVM + .vehicleCountryId.selectedId, + requestsVM.vehicleCountryId + .selectedOption, + "") + : null, + hint: LocaleKeys.country.tr(), + errorValue: + requestsVM.vehicleCountryId.errorValue, + ); + }), + if (requestsVM.vehicleCountryId.selectedId != + -1) ...[ + if (requestsVM.isCountryFetching) ...[ Row( - mainAxisAlignment: MainAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.center, children: [ - requestsVM.vehicleImageError.toText(fontSize: 14, color: Colors.red), + const CircularProgressIndicator() + .paddingAll(10) ], - ).paddingOnly(right: 10) - ], - if (requestsVM.pickedVehicleImages.isNotEmpty) ...[ - 16.height, - PickedFilesContainer( - pickedFiles: requestsVM.pickedVehicleImages, - onCrossPressedPrimary: requestsVM.removeImageFromList, - onAddFilePressed: () { - context.read().pickMultipleImages(); - }, ), + ] else ...[ + 8.height, + Builder(builder: (context) { + List vehicleCitiesDrop = []; + for (var element + in requestsVM.vehicleCities) { + vehicleCitiesDrop.add(DropValue( + element.id?.toInt() ?? 0, + element.cityName ?? "", + "")); + } + return DropdownField( + (DropValue value) => + requestsVM.updateSelectionVehicleCityId( + SelectionModel( + selectedId: value.id, + selectedOption: value.value)), + list: vehicleCitiesDrop, + dropdownValue: requestsVM + .vehicleCityId.selectedId != + -1 + ? DropValue( + requestsVM.vehicleCityId.selectedId, + requestsVM + .vehicleCityId.selectedOption, + "") + : null, + hint: LocaleKeys.city.tr(), + errorValue: + requestsVM.vehicleCityId.errorValue, + ); + }), ], - 16.height, + ], + 8.height, + TxtField( + hint: LocaleKeys.price.tr(), + value: requestsVM.price, + keyboardType: TextInputType.number, + onChanged: (e) => requestsVM.updatePrice(e), + ), + 8.height, + TxtField( + hint: LocaleKeys.description.tr(), + maxLines: 5, + value: requestsVM.description, + onChanged: (e) => requestsVM.updateDescription(e), + ), + 8.height, + DottedRectContainer( + onTap: () => context + .read() + .pickMultipleImages(), + text: LocaleKeys.attachImage.tr(), + icon: MyAssets.attachmentIcon.buildSvg(), + ), + if (requestsVM.vehicleImageError != "") ...[ + 10.height, Row( - mainAxisAlignment: MainAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.end, children: [ - Checkbox( - value: requestsVM.isShippingDeliveryEnabled, - onChanged: null, - ), - "Shipping/Delivery".toText(color: MyColors.darkPrimaryColor, isBold: true, fontSize: 18) + requestsVM.vehicleImageError + .toText(fontSize: 14, color: Colors.red), ], - ).onPress(() { - requestsVM.updateShippingDeliverEnabled(!requestsVM.isShippingDeliveryEnabled); - }), + ).paddingOnly(right: 10) ], - ), - ] + if (requestsVM.pickedVehicleImages.isNotEmpty) ...[ + 16.height, + PickedFilesContainer( + pickedFiles: requestsVM.pickedVehicleImages, + onCrossPressedPrimary: + requestsVM.removeImageFromList, + onAddFilePressed: () { + context + .read() + .pickMultipleImages(); + }, + ), + ], + 16.height, + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Checkbox( + value: requestsVM.isShippingDeliveryEnabled, + onChanged: null, + ), + LocaleKeys.shippingDelivery.tr().toText( + color: MyColors.darkPrimaryColor, + isBold: true, + fontSize: 18) + ], + ).onPress(() { + requestsVM.updateShippingDeliverEnabled( + !requestsVM.isShippingDeliveryEnabled); + }), + ], + ), + ] ], - ).toContainer(isShadowEnabled: true, marginAll: 16, paddingAll: 12), + ).toContainer( + isShadowEnabled: true, marginAll: 16, paddingAll: 12), ), ), ShowFillButton( - title: "Create Request", + title: LocaleKeys.createRequest.tr(), maxWidth: double.infinity, margin: const EdgeInsets.all(16), onPressed: () async { diff --git a/lib/views/requests/offer_list_page.dart b/lib/views/requests/offer_list_page.dart index 40c1a16..803511d 100644 --- a/lib/views/requests/offer_list_page.dart +++ b/lib/views/requests/offer_list_page.dart @@ -5,6 +5,7 @@ import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/models/requests_models/provider_offers_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; @@ -13,6 +14,7 @@ import 'package:mc_common_app/view_models/chat_view_model.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; class OfferListPage extends StatelessWidget { final OfferListPageArguments offerListPageArguments; @@ -21,23 +23,29 @@ class OfferListPage extends StatelessWidget { @override Widget build(BuildContext context) { - final List serviceProviderOffers = offerListPageArguments.serviceProviderOffers; + final List serviceProviderOffers = + offerListPageArguments.serviceProviderOffers; return Scaffold( - appBar: const CustomAppBar(title: "Offers"), + appBar: CustomAppBar(title: LocaleKeys.offers.tr()), body: serviceProviderOffers.isEmpty - ? Center(child: "No Offers to show.".toText(fontSize: 16, color: MyColors.lightTextColor)) + ? Center( + child: LocaleKeys.noOffersShow + .tr() + .toText(fontSize: 16, color: MyColors.lightTextColor)) : ListView.separated( itemCount: serviceProviderOffers.length, padding: const EdgeInsets.all(16), itemBuilder: (context, index) { - ServiceProvidersOffers offersModel = serviceProviderOffers[index]; + ServiceProvidersOffers offersModel = + serviceProviderOffers[index]; return Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - (offersModel.name ?? "").toText(fontSize: 16, isBold: true), + (offersModel.name ?? "") + .toText(fontSize: 16, isBold: true), Center( child: "${offersModel.offerCount}".toText( color: Colors.white, @@ -82,10 +90,12 @@ class OfferListPage extends StatelessWidget { ChatViewArguments chatViewArguments = ChatViewArguments( chatTypeEnum: ChatTypeEnum.requestOffer, receiverId: "${offersModel.providerUserId}", - senderId: AppState().getUser.data!.userInfo!.userId.toString(), + senderId: + AppState().getUser.data!.userInfo!.userId.toString(), requestId: offerListPageArguments.requestId, providerIndex: index, - requestIndex: -1, // This will be only send in case of provider + requestIndex: + -1, // This will be only send in case of provider ); final chatVM = context.read(); @@ -99,7 +109,8 @@ class OfferListPage extends StatelessWidget { providerOfferIndex: index, ) .whenComplete( - () => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments), + () => navigateWithName(context, AppRoutes.chatView, + arguments: chatViewArguments), ); }).toContainer(isShadowEnabled: true); }, diff --git a/lib/views/requests/widget/request_item.dart b/lib/views/requests/widget/request_item.dart index 4117e00..e46f050 100644 --- a/lib/views/requests/widget/request_item.dart +++ b/lib/views/requests/widget/request_item.dart @@ -2,6 +2,7 @@ import 'dart:developer'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/view_models/chat_view_model.dart'; import 'package:flutter/material.dart'; @@ -14,13 +15,18 @@ import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; +import 'package:easy_localization/easy_localization.dart'; class RequestItem extends StatelessWidget { final RequestModel request; final AppType appType; final int requestIndex; - const RequestItem({super.key, required this.request, required this.appType, required this.requestIndex}); + const RequestItem( + {super.key, + required this.request, + required this.appType, + required this.requestIndex}); @override Widget build(BuildContext context) { @@ -34,11 +40,16 @@ class RequestItem extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Utils.statusContainerChip(text: request.requestStatusName, chipColor: Utils.getChipColorByRequestStatus(request.requestStatus)), + Utils.statusContainerChip( + text: request.requestStatusName, + chipColor: Utils.getChipColorByRequestStatus( + request.requestStatus)), 6.height, - "${request.brand} ${request.model}".toText(fontSize: 16, isBold: true), - showItem("Model:", "${request.year}"), - showItem("Customer Name:", request.customerName), + "${request.brand} ${request.model}" + .toText(fontSize: 16, isBold: true), + showItem((LocaleKeys.model.tr()), "${request.year}"), + showItem( + (LocaleKeys.customerName.tr()), request.customerName), ], ), ), @@ -72,7 +83,7 @@ class RequestItem extends StatelessWidget { ) ], ), - showItem("Description: ", request.description), + showItem((LocaleKeys.description.tr()), request.description), showItem("Price Range: ", ""), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -87,7 +98,8 @@ class RequestItem extends StatelessWidget { isBold: true, ), 2.width, - "SAR" + LocaleKeys.sar + .tr() .toText( color: MyColors.lightTextColor, fontSize: 10, @@ -110,13 +122,20 @@ class RequestItem extends StatelessWidget { return; } if (appType == AppType.provider) { - RequestDetailPageArguments requestDetailPageArguments = RequestDetailPageArguments(requestIndex: requestIndex, requestModel: request); - navigateWithName(context, AppRoutes.requestsDetailPage, arguments: requestDetailPageArguments); + RequestDetailPageArguments requestDetailPageArguments = + RequestDetailPageArguments( + requestIndex: requestIndex, requestModel: request); + navigateWithName(context, AppRoutes.requestsDetailPage, + arguments: requestDetailPageArguments); } else { ChatVM chatVM = context.read(); - await chatVM.getOffersFromProvidersByRequest(requestId: request.id, context: context); - OfferListPageArguments offerListPageArguments = OfferListPageArguments(serviceProviderOffers: chatVM.serviceProviderOffersList, requestId: request.id); - navigateWithName(context, AppRoutes.offersListPage, arguments: offerListPageArguments); + await chatVM.getOffersFromProvidersByRequest( + requestId: request.id, context: context); + OfferListPageArguments offerListPageArguments = OfferListPageArguments( + serviceProviderOffers: chatVM.serviceProviderOffersList, + requestId: request.id); + navigateWithName(context, AppRoutes.offersListPage, + arguments: offerListPageArguments); } }); } diff --git a/lib/views/setting_options/provider_license_page.dart b/lib/views/setting_options/provider_license_page.dart index 89724c5..7ae9c9c 100644 --- a/lib/views/setting_options/provider_license_page.dart +++ b/lib/views/setting_options/provider_license_page.dart @@ -34,7 +34,8 @@ class _ProviderLicensePageState extends State { // TODO: implement initState super.initState(); branchVM = Provider.of(context, listen: false); - branchVM.getServiceProviderDocument(AppState().getUser.data!.userInfo!.providerId ?? 0); + branchVM.getServiceProviderDocument( + AppState().getUser.data!.userInfo!.providerId ?? 0); } @override @@ -73,7 +74,9 @@ class _ProviderLicensePageState extends State { if (validation(model)) { updateDocument(model); } else { - Utils.showToast("All document's are mandatory for Dealership Provider"); + Utils.showToast(LocaleKeys + .allDocumentMandatoryDealershipProvider + .tr()); } } else { updateDocument(model); @@ -102,7 +105,7 @@ class _ProviderLicensePageState extends State { MResponse res = await model.updateDocument(model.document!.data); Utils.hideLoading(context); if (res.messageStatus == 1) { - Utils.showToast("Documents uploaded successfully"); + Utils.showToast(LocaleKeys.documentsUploadedSuccessfully.tr()); } else { Utils.showToast(res.message ?? ""); } @@ -111,7 +114,7 @@ class _ProviderLicensePageState extends State { Widget showWidget(ServiceVM model) { if (model.state == ViewState.idle) { return model.document!.data!.isEmpty - ? Text("LocaleKeys.somethingWrong.tr()") + ? Text(LocaleKeys.somethingWrong.tr()) : ListView.separated( itemBuilder: (context, index) { return Column( @@ -124,19 +127,27 @@ class _ProviderLicensePageState extends State { ), ), Padding( - padding: const EdgeInsets.only(left: 20, right: 20, top: 4, bottom: 8), - child: LocaleKeys.enter_licence_detail.tr().toText(fontSize: 14, color: MyColors.lightTextColor, textAlign: TextAlign.center), + padding: const EdgeInsets.only( + left: 20, right: 20, top: 4, bottom: 8), + child: LocaleKeys.enter_licence_detail.tr().toText( + fontSize: 14, + color: MyColors.lightTextColor, + textAlign: TextAlign.center), ), TxtField( hint: LocaleKeys.description.tr(), maxLines: 3, isBackgroundEnabled: true, ), - if ((model.document?.data![index].documentUrl ?? "").toString().isNotEmpty) + if ((model.document?.data![index].documentUrl ?? "") + .toString() + .isNotEmpty) Column( children: [ 8.height, - (model.document?.data![index].documentUrl ?? "").toString().toText( + (model.document?.data![index].documentUrl ?? "") + .toString() + .toText( fontSize: 14, color: MyColors.lightTextColor, ), @@ -152,8 +163,10 @@ class _ProviderLicensePageState extends State { height: 45, decoration: BoxDecoration( color: Colors.transparent, - border: Border.all(color: MyColors.greyACColor, width: 2), - borderRadius: const BorderRadius.all(Radius.circular(0)), + border: + Border.all(color: MyColors.greyACColor, width: 2), + borderRadius: + const BorderRadius.all(Radius.circular(0)), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/views/setting_options/setting_option_help.dart b/lib/views/setting_options/setting_option_help.dart index f875f05..9768496 100644 --- a/lib/views/setting_options/setting_option_help.dart +++ b/lib/views/setting_options/setting_option_help.dart @@ -2,9 +2,11 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:easy_localization/easy_localization.dart'; class SettingOptionsHelp extends StatelessWidget { const SettingOptionsHelp({super.key}); @@ -13,7 +15,7 @@ class SettingOptionsHelp extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: "Help", + title: LocaleKeys.help.tr(), isRemoveBackButton: false, isDrawerEnabled: false, onBackButtonTapped: () => Navigator.pop(context), @@ -27,23 +29,30 @@ class SettingOptionsHelp extends StatelessWidget { children: [ CustomSettingOptionsTile( leadingWidget: const Icon(Icons.info_rounded, size: 20), - titleText: "FAQs", + titleText: LocaleKeys.faqs.tr(), needBorderBelow: true, onTap: () {}, ), CustomSettingOptionsTile( leadingWidget: const Icon(Icons.mail, size: 20), - titleText: "Contact Us", + titleText: LocaleKeys.contactUs.tr(), needBorderBelow: true, - onTap: () => navigateWithName(context, AppRoutes.settingOptionsFaqs), + onTap: () => navigateWithName( + context, AppRoutes.settingOptionsFaqs), ), CustomSettingOptionsTile( leadingWidget: const Icon(Icons.lock, size: 20), - titleText: "Term & Privacy", - onTap: () => navigateWithName(context, AppRoutes.profileView), + titleText: LocaleKeys.termPrivacy.tr(), + onTap: () => + navigateWithName(context, AppRoutes.profileView), ), ], - ).toContainer(width: double.infinity, isShadowEnabled: true, paddingAll: 10, margin: const EdgeInsets.fromLTRB(24, 24, 24, 0), borderRadius: 0), + ).toContainer( + width: double.infinity, + isShadowEnabled: true, + paddingAll: 10, + margin: const EdgeInsets.fromLTRB(24, 24, 24, 0), + borderRadius: 0), ], ), ), @@ -60,7 +69,13 @@ class CustomSettingOptionsTile extends StatelessWidget { final bool isForLanguage; final Function() onTap; - const CustomSettingOptionsTile({super.key, required this.leadingWidget, required this.onTap, required this.titleText, this.needBorderBelow = false, this.isForLanguage = false}); + const CustomSettingOptionsTile( + {super.key, + required this.leadingWidget, + required this.onTap, + required this.titleText, + this.needBorderBelow = false, + this.isForLanguage = false}); @override Widget build(BuildContext context) { @@ -76,7 +91,9 @@ class CustomSettingOptionsTile extends StatelessWidget { titleText.toText(fontSize: 16), ], ), - isForLanguage ? const Icon(Icons.language, size: 18) : const Icon(Icons.arrow_forward, size: 18) + isForLanguage + ? const Icon(Icons.language, size: 18) + : const Icon(Icons.arrow_forward, size: 18) ], ).onPress(onTap), 5.height, diff --git a/lib/views/setting_options/setting_options_faqs.dart b/lib/views/setting_options/setting_options_faqs.dart index ed0d8eb..fb3abde 100644 --- a/lib/views/setting_options/setting_options_faqs.dart +++ b/lib/views/setting_options/setting_options_faqs.dart @@ -1,8 +1,10 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/views/setting_options/widgets/custom_setting_options_tile.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:easy_localization/easy_localization.dart'; class SettingOptionsFAQs extends StatelessWidget { const SettingOptionsFAQs({super.key}); @@ -11,7 +13,7 @@ class SettingOptionsFAQs extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: "More", + title: LocaleKeys.more.tr(), isRemoveBackButton: false, isDrawerEnabled: false, onBackButtonTapped: () => Navigator.pop(context), @@ -23,11 +25,27 @@ class SettingOptionsFAQs extends StatelessWidget { children: [ Column( children: [ - CustomSettingOptionsTile(leadingWidget: const Icon(Icons.info, size: 20), titleText: "FAQs", needBorderBelow: true, onTap: () {}), - CustomSettingOptionsTile(leadingWidget: const Icon(Icons.mail, size: 20), titleText: "Contact Us", needBorderBelow: true, onTap: () {}), - CustomSettingOptionsTile(leadingWidget: const Icon(Icons.settings, size: 20), titleText: "Terms & Privacy", onTap: () {}), + CustomSettingOptionsTile( + leadingWidget: const Icon(Icons.info, size: 20), + titleText: LocaleKeys.faqs.tr(), + needBorderBelow: true, + onTap: () {}), + CustomSettingOptionsTile( + leadingWidget: const Icon(Icons.mail, size: 20), + titleText: LocaleKeys.contactUs.tr(), + needBorderBelow: true, + onTap: () {}), + CustomSettingOptionsTile( + leadingWidget: const Icon(Icons.settings, size: 20), + titleText: LocaleKeys.termPrivacy.tr(), + onTap: () {}), ], - ).toContainer(width: double.infinity, isShadowEnabled: true, paddingAll: 10, margin: const EdgeInsets.fromLTRB(24, 24, 24, 0), borderRadius: 0), + ).toContainer( + width: double.infinity, + isShadowEnabled: true, + paddingAll: 10, + margin: const EdgeInsets.fromLTRB(24, 24, 24, 0), + borderRadius: 0), ], ), ), diff --git a/lib/views/setting_options/setting_options_invite_friends.dart b/lib/views/setting_options/setting_options_invite_friends.dart index cb9512f..2d48e3f 100644 --- a/lib/views/setting_options/setting_options_invite_friends.dart +++ b/lib/views/setting_options/setting_options_invite_friends.dart @@ -2,9 +2,11 @@ import 'package:flutter/material.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:easy_localization/easy_localization.dart'; class SettingOptionsInviteFriends extends StatelessWidget { const SettingOptionsInviteFriends({super.key}); @@ -13,7 +15,7 @@ class SettingOptionsInviteFriends extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: "More", + title: LocaleKeys.more.tr(), isRemoveBackButton: false, isDrawerEnabled: false, onBackButtonTapped: () => Navigator.pop(context), @@ -27,23 +29,30 @@ class SettingOptionsInviteFriends extends StatelessWidget { children: [ CustomSettingOptionsTile( leadingWidget: const Icon(Icons.person, size: 20), - titleText: "Invite Friends", + titleText: LocaleKeys.inviteFriends.tr(), needBorderBelow: true, onTap: () {}, ), CustomSettingOptionsTile( leadingWidget: const Icon(Icons.help, size: 20), - titleText: "Help", + titleText: LocaleKeys.help.tr(), needBorderBelow: true, - onTap: () => navigateWithName(context, AppRoutes.settingOptionsFaqs), + onTap: () => navigateWithName( + context, AppRoutes.settingOptionsFaqs), ), CustomSettingOptionsTile( leadingWidget: const Icon(Icons.person, size: 20), - titleText: "Account", - onTap: () => navigateWithName(context, AppRoutes.profileView), + titleText: LocaleKeys.account.tr(), + onTap: () => + navigateWithName(context, AppRoutes.profileView), ), ], - ).toContainer(width: double.infinity, isShadowEnabled: true, paddingAll: 10, margin: const EdgeInsets.fromLTRB(24, 24, 24, 0), borderRadius: 0), + ).toContainer( + width: double.infinity, + isShadowEnabled: true, + paddingAll: 10, + margin: const EdgeInsets.fromLTRB(24, 24, 24, 0), + borderRadius: 0), ], ), ), @@ -60,7 +69,13 @@ class CustomSettingOptionsTile extends StatelessWidget { final bool isForLanguage; final Function() onTap; - const CustomSettingOptionsTile({super.key, required this.leadingWidget, required this.onTap, required this.titleText, this.needBorderBelow = false, this.isForLanguage = false}); + const CustomSettingOptionsTile( + {super.key, + required this.leadingWidget, + required this.onTap, + required this.titleText, + this.needBorderBelow = false, + this.isForLanguage = false}); @override Widget build(BuildContext context) { @@ -76,7 +91,9 @@ class CustomSettingOptionsTile extends StatelessWidget { titleText.toText(fontSize: 16), ], ), - isForLanguage ? const Icon(Icons.language, size: 18) : const Icon(Icons.arrow_forward, size: 18) + isForLanguage + ? const Icon(Icons.language, size: 18) + : const Icon(Icons.arrow_forward, size: 18) ], ).onPress(onTap), 5.height, diff --git a/lib/views/setting_options/setting_options_language.dart b/lib/views/setting_options/setting_options_language.dart index 0e4f413..69a5bea 100644 --- a/lib/views/setting_options/setting_options_language.dart +++ b/lib/views/setting_options/setting_options_language.dart @@ -5,6 +5,7 @@ import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/navigator.dart'; @@ -22,7 +23,7 @@ class SettingOptionsLanguage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: CustomAppBar( - title: "More", + title: LocaleKeys.more.tr(), isRemoveBackButton: false, isDrawerEnabled: false, onBackButtonTapped: () => Navigator.pop(context), @@ -39,8 +40,9 @@ class SettingOptionsLanguage extends StatelessWidget { Column( children: [ CustomSettingOptionsTile( - leadingWidget: const Icon(Icons.quickreply_outlined, size: 20), - titleText: "Requests", + leadingWidget: + const Icon(Icons.quickreply_outlined, size: 20), + titleText: LocaleKeys.requests.tr(), needBorderBelow: true, onTap: () { context.read().onNavbarTapped(4); @@ -48,20 +50,22 @@ class SettingOptionsLanguage extends StatelessWidget { }), CustomSettingOptionsTile( leadingWidget: const Icon(Icons.settings, size: 20), - titleText: "Settings", + titleText: LocaleKeys.settings.tr(), needBorderBelow: true, onTap: () {}, //navigateWithName(context, AppRoutes.settingOptionsInviteFriends), ), CustomSettingOptionsTile( - leadingWidget: const Icon(Icons.question_mark_outlined, size: 20), - titleText: "Help", + leadingWidget: + const Icon(Icons.question_mark_outlined, size: 20), + titleText: LocaleKeys.help.tr(), needBorderBelow: true, - onTap: () => navigateWithName(context, AppRoutes.settingOptionsHelp), + onTap: () => + navigateWithName(context, AppRoutes.settingOptionsHelp), ), CustomSettingOptionsTile( leadingWidget: const Icon(Icons.person, size: 20), - titleText: "Account", + titleText: LocaleKeys.account.tr(), needBorderBelow: false, onTap: () { navigateWithName(context, AppRoutes.profileView); @@ -69,20 +73,29 @@ class SettingOptionsLanguage extends StatelessWidget { // Navigator.pop(context); }), ], - ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0), + ).toWhiteContainer( + width: double.infinity, + pading: const EdgeInsets.all(12), + borderRadius: 0), 10.height, CustomSettingOptionsTile( leadingWidget: const Icon(Icons.translate, size: 20), - titleText: "Language", + titleText: LocaleKeys.language.tr(), isForLanguage: true, onTap: () { - if (EasyLocalization.of(context)?.currentLocale?.countryCode == "SA") { + if (EasyLocalization.of(context) + ?.currentLocale + ?.countryCode == + "SA") { context.setLocale(const Locale("en", "US")); } else { context.setLocale(const Locale('ar', 'SA')); } }, - ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0), + ).toWhiteContainer( + width: double.infinity, + pading: const EdgeInsets.all(12), + borderRadius: 0), 10.height, (AppState().currentAppType == AppType.provider) ? Column( @@ -96,12 +109,13 @@ class SettingOptionsLanguage extends StatelessWidget { color: MyColors.primaryColor, ), ), - titleText: "My Subscriptions", + titleText: LocaleKeys.mySubscriptions.tr(), subTitle: "Silver", isForLanguage: false, needBorderBelow: true, onTap: () { - navigateWithName(context, AppRoutes.mySubscriptionsPage); + navigateWithName( + context, AppRoutes.mySubscriptionsPage); }, ), CustomSettingOptionsTile( @@ -113,12 +127,13 @@ class SettingOptionsLanguage extends StatelessWidget { // color: MyColors.primaryColor, ), ), - titleText: "Subscriptions", + titleText: LocaleKeys.subscriptions.tr(), subTitle: null, isForLanguage: false, needBorderBelow: true, onTap: () { - navigateWithName(context, AppRoutes.subscriptionsPage); + navigateWithName( + context, AppRoutes.subscriptionsPage); }, ), CustomSettingOptionsTile( @@ -130,18 +145,24 @@ class SettingOptionsLanguage extends StatelessWidget { // color: MyColors.primaryColor, ), ), - titleText: "Define Licenses", + titleText: LocaleKeys.defineLicenses.tr(), subTitle: null, isForLanguage: false, needBorderBelow: false, onTap: () { - navigateWithName(context, AppRoutes.providerLicensePage); + navigateWithName( + context, AppRoutes.providerLicensePage); }, ) ], - ).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0) + ).toWhiteContainer( + width: double.infinity, + pading: const EdgeInsets.all(12), + borderRadius: 0) + : SizedBox(), + (AppState().currentAppType == AppType.provider) + ? 10.height : SizedBox(), - (AppState().currentAppType == AppType.provider) ? 10.height : SizedBox(), ], )), // : Expanded( @@ -167,7 +188,9 @@ class SettingOptionsLanguage extends StatelessWidget { // ], // ), // ), - (AppState().currentAppType == AppType.provider) ? const Text("Provider") : const Text("Customer"), + (AppState().currentAppType == AppType.provider) + ? Text(LocaleKeys.provider.tr()) + : Text(LocaleKeys.customer.tr()), Row( children: [ Expanded( @@ -177,7 +200,7 @@ class SettingOptionsLanguage extends StatelessWidget { isFilled: false, fontSize: 16, maxHeight: 55, - title: "Log Out", + title: LocaleKeys.logOut.tr(), onPressed: () {}, ), ), diff --git a/lib/views/user/login_method_selection_page.dart b/lib/views/user/login_method_selection_page.dart index 2f465d8..76b1d28 100644 --- a/lib/views/user/login_method_selection_page.dart +++ b/lib/views/user/login_method_selection_page.dart @@ -1,18 +1,22 @@ import 'dart:async'; import 'dart:io'; +import 'package:flutter/cupertino.dart'; import 'package:local_auth/local_auth.dart'; import 'package:mc_common_app/classes/app_state.dart'; import 'package:mc_common_app/classes/consts.dart'; import 'package:mc_common_app/config/dependencies.dart'; +import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; +import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/view_models/user_view_model.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/button/show_image_button.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:provider/provider.dart'; class LoginMethodSelectionPage extends StatefulWidget { @@ -54,12 +58,14 @@ class _LoginMethodSelectionPageState extends State { Expanded( child: ShowImageButton( onClick: () { - userVM.verifiyAuth(context: context, userToken: widget.userToken, apptype: appState.currentAppType, loginType: "3" ); + userVM.verifiyAuth(context: context, userToken: widget.userToken, apptype: appState.currentAppType, loginType: "3"); //userVM.performBasicOtpLoginSelectionPage(context, userToken: userToken,appType: appState.currentAppType); }, title: LocaleKeys.fingerPrint.tr(), icon: MyAssets.icFingerprintSvg, - isDisabled: userVM.isBioAvailable(Platform.isAndroid ? BiometricType.weak : BiometricType.fingerprint, ), + isDisabled: userVM.isBioAvailable( + Platform.isAndroid ? BiometricType.weak : BiometricType.fingerprint, + ), ), ), 20.width, @@ -67,7 +73,7 @@ class _LoginMethodSelectionPageState extends State { child: ShowImageButton( onClick: () { // userVM.performBasicOtpLoginSelectionPage(context, userToken: widget.userToken, appType: appState.currentAppType); - userVM.verifiyAuth(context: context, userToken: widget.userToken, apptype: appState.currentAppType, loginType: "4" ); + userVM.verifiyAuth(context: context, userToken: widget.userToken, apptype: appState.currentAppType, loginType: "4"); }, title: LocaleKeys.faceRecognition.tr(), icon: MyAssets.icFace, @@ -82,7 +88,7 @@ class _LoginMethodSelectionPageState extends State { Expanded( child: ShowImageButton( onClick: () { - userVM.performBasicOtpLoginSelectionPage(context, userToken: widget.userToken, appType: appState.currentAppType,loginType: "1"); + userVM.performBasicOtpLoginSelectionPage(context, userToken: widget.userToken, appType: appState.currentAppType, loginType: "1"); }, title: LocaleKeys.SMS.tr(), icon: MyAssets.icSmsSvg, @@ -101,6 +107,16 @@ class _LoginMethodSelectionPageState extends State { ), ], ), + 150.height, + ("Login To Another Account") + .toText( + fontSize: 20, + letterSpacing: -1.44, + ) + .onPress(() { + userVM.otherLogin(context); + }), + 30.height, ], ), ),