Merge remote-tracking branch 'origin/faiz_development_common' into faiz_development_common

aamir_dev
FaizHashmiCS22 12 months ago
commit 462c8fa104

@ -329,7 +329,7 @@
"vehiclePart": "جزء المركبة",
"damagePartPictures": "صور الأجزاء المتضررة",
"vehicleDamagePart": "جزء المركبة المتضرر",
"duration": ":المدة",
"duration": "المدة",
"specialServices": "الخدمات الخاصة",
"specialService": "خدمة خاصة",
"adContactDetails": "تفاصيل الاتصال بالإعلان",
@ -685,5 +685,25 @@
"noItemsToShow": "لا توجد عناصر لعرضها.",
"serviceItem": "عنصر الخدمة",
"createdBy": "تم الإنشاء بواسطة",
"createGroupServices": "إنشاء خدمات المجموعة"
"createGroupServices": "إنشاء خدمات المجموعة",
"logoutConfirmation": "هل أنت متأكد أنك تريد تسجيل الخروج؟",
"logoutConfirmationMessage": "سيتم تسجيل خروجك من التطبيق وسيتعين عليك إضافة اسم المستخدم وكلمة المرور مرة أخرى لتسجيل الدخول.",
"addToFavoritesOn": "تمت الإضافة إلى المفضلة في:",
"subscriptionDate": "تاريخ الاشتراك",
"expiresOn": "تنتهي صلاحيته",
"expired": "منتهي الصلاحية",
"upgradeBranches": "قم بترقية اشتراكك لإضافة المزيد من الفروع.",
"upgradeAds": "قم بترقية اشتراكك لإضافة المزيد من الإعلانات.",
"upgradeSubUsers": "قم بترقية اشتراكك لإضافة المزيد من المستخدمين الفرعيين.",
"explore": "استكشاف",
"manageRequests": "إدارة الطلبات",
"serviceNotAvailableAtHomeLocation": "الخدمة المختارة غير متوفرة في الموقع المحدد.",
"noAvailableItems": "لا توجد عناصر متاحة.",
"wantToRescheduleAppointment": "أرغب في إعادة جدولة الموعد.",
"noNeedForService": "لا أحتاج هذه الخدمة بعد الآن.",
"testTheService": "اختبر الخدمة.",
"companyLocation": "موقع الشركة",
"customerLocation": "موقع العميل",
"deliveryAvailable": "التوصيل متاح",
"viewed": "تم المشاهدة"
}

@ -329,7 +329,7 @@
"vehiclePart": "Vehicle Part",
"damagePartPictures": "Damage Part Pictures",
"vehicleDamagePart": "Vehicle Damage Part",
"duration": "Duration:",
"duration": "Duration",
"specialServices": "Special Services",
"specialService": "Special Service",
"adContactDetails": "Ad Contact Details",
@ -680,8 +680,28 @@
"users": "Users",
"adsRemaining": "Ads Remaining",
"attachPDF": "Attach PDF",
"noItemsToShow": "No Items to show.",
"serviceItem": "Service Item",
"createdBy": "Created By",
"createGroupServices": "Create Group Services"
"createGroupServices": "Create Group Services",
"logoutConfirmation": "Are you sure you want want to Logout?",
"logoutConfirmationMessage": "You will be logged out of the application and you have to add your username and password again to login",
"addToFavoritesOn": "Added to Favorites on:",
"subscriptionDate": "Subscription Date",
"expiresOn": "Expires On",
"expired": "Expired",
"upgradeBranches": "Upgrade your subscription to add more Branches.",
"upgradeAds": "Upgrade your subscription to add more Ads.",
"upgradeSubUsers": "Upgrade your subscription to add more Sub Users.",
"explore": "Explore",
"manageRequests": "Manage Requests",
"serviceNotAvailableAtHomeLocation": "The Selected Service is not available at Home Location.",
"noAvailableItems": "There are no available items.",
"wantToRescheduleAppointment": "I want to reschedule the appointment.",
"noNeedForService": "I do not need this service anymore.",
"testTheService": "Test the service.",
"companyLocation": "Company Location",
"customerLocation": "Customer Location",
"deliveryAvailable": "Delivery Available",
"viewed": "Viewed"
}

@ -1,5 +1,9 @@
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/generated/codegen_loader.g.dart';
import 'package:mc_common_app/utils/enums.dart';
class ApiConsts {
// static String baseUrl = "http://10.200.204.20:2801/"; // Local server
@ -176,14 +180,30 @@ class ApiConsts {
//Settings Options
static String getAllFAQs = "${baseUrlServices}api/Common/FAQ_Get";
static String getAppInvitationLink = "${baseUrlServices}api/Common/AppInvitation_Get";
static String createAppInvitation = "${baseUrlServices}api/Common/AppInvitation_Create";
static String getContactInfo = "${baseUrlServices}api/Master/ContactInfo_Get";
static String getAppInfo = "${baseUrlServices}api/Master/AppInfo_Get";
static String getTermsAndConditions = "${baseUrlServices}api/Master/TermAndCondition_Get";
static List<String> closingUrls = ["PayFortResponse"];
}
class GlobalConsts {
static String appNameCustomer = "MOWATER Customer";
static String appNameProvider = "MOWATER Provider";
//Android
static String appPackageNameCustomerAndroid = "com.cloud.solutions.mowater.ksa.customer";
static String appPackageNameProviderAndroid = "com.cloud.solutions.mowater.ksa.provider";
static String appPlayStoreLinkCustomerAndroid = "https://play.google.com/store/apps/details?id=$appPackageNameCustomerAndroid";
static String appPlayStoreLinkProviderAndroid = "https://play.google.com/store/apps/details?id=$appPackageNameProviderAndroid";
//IOS
static String appIDCustomerIOS = "";
static String appIDProviderIOS = "";
static String appAppStoreStoreLinkCustomerIos = "https://apps.apple.com/us/app/$appIDCustomerIOS";
static String appAppStoreStoreLinkProviderIos = "https://apps.apple.com/us/app/$appIDProviderIOS";
static String isRememberMe = "remember_me";
static String email = "email";
static String password = "password";
@ -193,7 +213,7 @@ class GlobalConsts {
static String doNotShowWelcomeVideo = "doNotShowWelcomeVideo";
static String demandAmountError = "Amount Cannot be Empty";
static String reservationCancelError = "Cancellation Reason Cannot be Empty";
static String descriptionError = "Description Cannot be Empty";
static String descriptionError = "Description should be more than 5 letters.";
static String acceptingThisOffer = "I am accepting this offer.";
static String vehicleVinError = "Vehicle VIN Cannot be Empty";
static String vehicleTitleError = "Vehicle Title Cannot be Empty";
@ -208,6 +228,26 @@ class GlobalConsts {
static String fillAllFields = "Please fill out all the fields.";
static String requestTypeCannotBeEmpty = "Request type cannot be empty.";
static String reserveAdPriceInfo = "Some dummy description to explain the following concept. This price will be for 24 hours and if a user cancels the reservations before 24 hours then the amount will be automatically refunded to the buyer.";
static String appInvitationMessageEn = "🚗 Hey , check out MOWATER to book car services, buy/sell vehicles, and more—join here! [Invite Link]";
static String getAppInvitationLink() {
String appInvitationMessageEn = "";
if (Platform.isAndroid) {
if (AppState().currentAppType == AppType.customer) {
appInvitationMessageEn = "🚗 Hey , check out $appNameCustomer to book car services, buy/sell vehicles, and more—join here! \n\n $appPlayStoreLinkCustomerAndroid";
} else {
appInvitationMessageEn = "🚗 Hey , check out $appNameProvider to book car services, buy/sell vehicles, and more—join here! \n\n $appPlayStoreLinkProviderAndroid";
}
} else if (Platform.isIOS) {
if (AppState().currentAppType == AppType.customer) {
appInvitationMessageEn = "🚗 Hey , check out $appNameCustomer to book car services, buy/sell vehicles, and more—join here! \n\n $appPlayStoreLinkCustomerAndroid";
} else {
appInvitationMessageEn = "🚗 Hey , check out $appNameProvider to book car services, buy/sell vehicles, and more—join here! \n\n $appPlayStoreLinkProviderAndroid";
}
}
return appInvitationMessageEn;
}
}
class MyAssets {

@ -25,6 +25,7 @@ import 'package:mc_common_app/views/setting_options/setting_options_contact_us.d
import 'package:mc_common_app/views/setting_options/setting_options_faqs.dart';
import 'package:mc_common_app/views/setting_options/setting_options_invite_friends.dart';
import 'package:mc_common_app/views/setting_options/setting_options_more.dart';
import 'package:mc_common_app/views/setting_options/setting_options_terms_and_conditions.dart';
import 'package:mc_common_app/views/shipping_management/shipping_management_view.dart';
import 'package:mc_common_app/views/user/change_email_page.dart';
import 'package:mc_common_app/views/user/change_mobile_page.dart';
@ -128,7 +129,6 @@ class AppRoutes {
static const String paymentMethodsView = "/paymentMethodsView";
//Shipping
static const shippingManagementView = "/shippingManagementView";
//Customer APP: Provider & Services
@ -150,6 +150,7 @@ class AppRoutes {
static const String settingOptionsFaqs = "/settingOptionsFaqs";
static const String settingOptionsContactUs = "/settingOptionsContactUs";
static const String settingOptionsAppInfo = "/settingOptionsAppInfo";
static const String settingOptionsTermsAndConditions = "/settingOptionsTermsAndConditions";
static const String settingOptionsMore = "/settingOptionsLanguages";
static const String settingOptionsInviteFriends = "/settingOptionsInviteFriends";
static const String settingOptionsHelp = "/settingOptionsHelp";
@ -201,6 +202,7 @@ class AppRoutes {
AppRoutes.settingOptionsFaqs: (context) => const SettingOptionsFAQs(),
AppRoutes.settingOptionsContactUs: (context) => const SettingOptionsContactUs(),
AppRoutes.settingOptionsAppInfo: (context) => const SettingOptionsAppInfo(),
AppRoutes.settingOptionsTermsAndConditions: (context) => const SettingOptionsTermsAndConditions(),
AppRoutes.settingOptionsInviteFriends: (context) => const SettingOptionsInviteFriends(),
AppRoutes.paymentMethodsView: (context) => PaymentMethodsView(paymentType: ModalRoute.of(context)!.settings.arguments as PaymentTypes),
//Requests

@ -345,7 +345,7 @@ class CodegenLoader extends AssetLoader{
"vehiclePart": "جزء المركبة",
"damagePartPictures": "صور الأجزاء المتضررة",
"vehicleDamagePart": "جزء المركبة المتضرر",
"duration": ":المدة",
"duration": "المدة",
"specialServices": "الخدمات الخاصة",
"specialService": "خدمة خاصة",
"adContactDetails": "تفاصيل الاتصال بالإعلان",
@ -701,7 +701,27 @@ class CodegenLoader extends AssetLoader{
"noItemsToShow": "لا توجد عناصر لعرضها.",
"serviceItem": "عنصر الخدمة",
"createdBy": "تم الإنشاء بواسطة",
"createGroupServices": "إنشاء خدمات المجموعة"
"createGroupServices": "إنشاء خدمات المجموعة",
"logoutConfirmation": "هل أنت متأكد أنك تريد تسجيل الخروج؟",
"logoutConfirmationMessage": "سيتم تسجيل خروجك من التطبيق وسيتعين عليك إضافة اسم المستخدم وكلمة المرور مرة أخرى لتسجيل الدخول.",
"addToFavoritesOn": "تمت الإضافة إلى المفضلة في:",
"subscriptionDate": "تاريخ الاشتراك",
"expiresOn": "تنتهي صلاحيته",
"expired": "منتهي الصلاحية",
"upgradeBranches": "قم بترقية اشتراكك لإضافة المزيد من الفروع.",
"upgradeAds": "قم بترقية اشتراكك لإضافة المزيد من الإعلانات.",
"upgradeSubUsers": "قم بترقية اشتراكك لإضافة المزيد من المستخدمين الفرعيين.",
"explore": "استكشاف",
"manageRequests": "إدارة الطلبات",
"serviceNotAvailableAtHomeLocation": "الخدمة المختارة غير متوفرة في الموقع المحدد.",
"noAvailableItems": "لا توجد عناصر متاحة.",
"wantToRescheduleAppointment": "أرغب في إعادة جدولة الموعد.",
"noNeedForService": "لا أحتاج هذه الخدمة بعد الآن.",
"testTheService": "اختبر الخدمة.",
"companyLocation": "موقع الشركة",
"customerLocation": "موقع العميل",
"deliveryAvailable": "التوصيل متاح",
"viewed": "تم المشاهدة"
};
static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In",
@ -1034,7 +1054,7 @@ static const Map<String,dynamic> en_US = {
"vehiclePart": "Vehicle Part",
"damagePartPictures": "Damage Part Pictures",
"vehicleDamagePart": "Vehicle Damage Part",
"duration": "Duration:",
"duration": "Duration",
"specialServices": "Special Services",
"specialService": "Special Service",
"adContactDetails": "Ad Contact Details",
@ -1385,10 +1405,29 @@ static const Map<String,dynamic> en_US = {
"users": "Users",
"adsRemaining": "Ads Remaining",
"attachPDF": "Attach PDF",
"noItemsToShow": "No Items to show.",
"serviceItem": "Service Item",
"createdBy": "Created By",
"createGroupServices": "Create Group Services"
"createGroupServices": "Create Group Services",
"logoutConfirmation": "Are you sure you want want to Logout?",
"logoutConfirmationMessage": "You will be logged out of the application and you have to add your username and password again to login",
"addToFavoritesOn": "Added to Favorites on:",
"subscriptionDate": "Subscription Date",
"expiresOn": "Expires On",
"expired": "Expired",
"upgradeBranches": "Upgrade your subscription to add more Branches.",
"upgradeAds": "Upgrade your subscription to add more Ads.",
"upgradeSubUsers": "Upgrade your subscription to add more Sub Users.",
"explore": "Explore",
"manageRequests": "Manage Requests",
"serviceNotAvailableAtHomeLocation": "The Selected Service is not available at Home Location.",
"noAvailableItems": "There are no available items.",
"wantToRescheduleAppointment": "I want to reschedule the appointment.",
"noNeedForService": "I do not need this service anymore.",
"testTheService": "Test the service.",
"companyLocation": "Company Location",
"customerLocation": "Customer Location",
"deliveryAvailable": "Delivery Available",
"viewed": "Viewed"
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};
}

@ -665,5 +665,25 @@ abstract class LocaleKeys {
static const serviceItem = 'serviceItem';
static const createdBy = 'createdBy';
static const createGroupServices = 'createGroupServices';
static const logoutConfirmation = 'logoutConfirmation';
static const logoutConfirmationMessage = 'logoutConfirmationMessage';
static const addToFavoritesOn = 'addToFavoritesOn';
static const subscriptionDate = 'subscriptionDate';
static const expiresOn = 'expiresOn';
static const expired = 'expired';
static const upgradeBranches = 'upgradeBranches';
static const upgradeAds = 'upgradeAds';
static const upgradeSubUsers = 'upgradeSubUsers';
static const explore = 'explore';
static const manageRequests = 'manageRequests';
static const serviceNotAvailableAtHomeLocation = 'serviceNotAvailableAtHomeLocation';
static const noAvailableItems = 'noAvailableItems';
static const wantToRescheduleAppointment = 'wantToRescheduleAppointment';
static const noNeedForService = 'noNeedForService';
static const testTheService = 'testTheService';
static const companyLocation = 'companyLocation';
static const customerLocation = 'customerLocation';
static const deliveryAvailable = 'deliveryAvailable';
static const viewed = 'viewed';
}

@ -2,6 +2,7 @@ import 'package:logger/logger.dart';
Logger logger = Logger(printer: PrettyPrinter(printEmojis: false, colors: true, printTime: false));
bool disableThingsForQA = true;
// Language Tile in Settings

@ -33,21 +33,7 @@ class BranchDetailModel {
bool isExpanded = false;
bool? isFavorite;
//I/flutter (23146): "id": 1021,
// I/flutter (23146): "serviceProviderID": 10,
// I/flutter (23146): "serviceProviderName": "string",
// I/flutter (23146): "cityID": 1,
// I/flutter (23146): "cityName": "Riyadh",
// I/flutter (23146): "branchName": "Al Arouba Cars",
// I/flutter (23146): "branchDescription": "des",
// I/flutter (23146): "address": "3289 Hilal Bin Omayah St - حي العليا, حي العليا, الرياض, RHOD3289, Saudi Arabia",
// I/flutter (23146): "latitude": "24.708521303151027",
// I/flutter (23146): "longitude": "46.666924171149724",
// I/flutter (23146): "distanceKM": 0.0,
// I/flutter (23146): "openTime": "09:00",
// I/flutter (23146): "closeTime": "18:00",
// I/flutter (23146): "branchStatus": 3,
// I/flutter (23146): "branchStatusText": "ApprovedOrActive",
BranchDetailModel({
this.id,
this.serviceProviderId,

@ -6,20 +6,24 @@ class AppInfoModel {
String? content;
bool? isActive;
int? channel;
List<ImageModel>? appInfoImages;
List<ImageModel>? images;
AppInfoModel({this.id, this.header, this.content, this.isActive, this.channel, this.appInfoImages});
AppInfoModel({this.id, this.header, this.content, this.isActive, this.channel, this.images});
AppInfoModel.fromJson(Map<String, dynamic> json) {
AppInfoModel.fromJson(Map<String, dynamic> json, {bool isForTermsAndCondition = false}) {
String imagesKey = "appInfoImages";
if (isForTermsAndCondition) {
imagesKey = "termAndConditionImages";
}
id = json['id'];
header = json['header'];
content = json['content'];
isActive = json['isActive'];
channel = json['channel'];
if (json['appInfoImages'] != null) {
appInfoImages = <ImageModel>[];
json['appInfoImages'].forEach((v) {
appInfoImages!.add(ImageModel.fromJson(v));
if (json[imagesKey] != null) {
images = <ImageModel>[];
json[imagesKey].forEach((v) {
images!.add(ImageModel.fromJson(v));
});
}
}

@ -10,8 +10,6 @@ import '../../utils/enums.dart';
Subscription subscriptionFromJson(String str) => Subscription.fromJson(json.decode(str));
String subscriptionToJson(Subscription data) => json.encode(data.toJson());
class SubscriptionModel {
SubscriptionModel({
this.messageStatus,
@ -31,13 +29,6 @@ class SubscriptionModel {
data: json["data"] == null ? [] : List<Subscription>.from(json["data"]!.map((x) => Subscription.fromJson(x))),
message: json["message"],
);
Map<String, dynamic> toJson() => {
"messageStatus": messageStatus,
"totalItemsCount": totalItemsCount,
"data": data == null ? [] : List<dynamic>.from(data!.map((x) => x.toJson())),
"message": message,
};
}
class Subscription {
@ -83,8 +74,8 @@ class Subscription {
bool? isSubscribed;
int? subscriptionAppliedId;
int? serviceProviderId;
DateTime? dateStart;
DateTime? dateEnd;
String? dateStart;
String? dateEnd;
bool? isExpired;
bool? isActive;
SubscriptionTypeEnum? subscriptionTypeEnum;
@ -114,8 +105,8 @@ class Subscription {
isSubscribed: json["isSubscribed"],
subscriptionAppliedId: json["subscriptionAppliedID"],
serviceProviderId: json["serviceProviderID"],
dateStart: json["dateStart"] == null ? null : DateTime.parse(json["dateStart"]),
dateEnd: json["dateEnd"] == null ? null : DateTime.parse(json["dateEnd"]),
dateStart: json["dateStart"],
dateEnd: json["dateEnd"],
isExpired: json["isExpired"],
isActive: json["isActive"],
isMyCurrentPackage: false,
@ -131,33 +122,4 @@ class Subscription {
subUsersRemaining: json["subUsersRemaining"],
adsRemaining: json["adsRemaining"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"description": description,
"durationName": durationName,
"durationDays": durationDays,
"price": price,
"currency": currency,
"countryID": countryId,
"countryName": countryName,
"isSubscribed": isSubscribed,
"subscriptionAppliedID": subscriptionAppliedId,
"serviceProviderID": serviceProviderId,
"dateStart": dateStart?.toIso8601String(),
"dateEnd": dateEnd?.toIso8601String(),
"isExpired": isExpired,
"isActive": isActive,
"isRenewable": isRenewable,
"subscriptionBranches": subscriptionBranches,
"subscriptionSubUsers": subscriptionSubUsers,
"subscriptionAds": subscriptionAds,
"totalBranches": totalBranches,
"totalSubUsers": totalSubUsers,
"totalAds": totalAds,
"branchesRemaining": branchesRemaining,
"subUsersRemaining": subUsersRemaining,
"adsRemaining": adsRemaining,
};
}

@ -16,7 +16,7 @@ import 'package:mc_common_app/utils/enums.dart';
abstract class AdsRepo {
Future<List<AdsDurationModel>> getAdsDuration();
Future<List<SpecialServiceModel>> getSpecialServices({required int specialServiceId});
Future<List<SpecialServiceModel>> getSpecialServices({required int specialServiceType});
Future<GenericRespModel> createOrUpdateAd({required AdsCreationPayloadModel adsCreationPayloadModel, required bool isCreateNew});
@ -63,9 +63,9 @@ class AdsRepoImp implements AdsRepo {
}
@override
Future<List<SpecialServiceModel>> getSpecialServices({required int specialServiceId}) async {
Future<List<SpecialServiceModel>> getSpecialServices({required int specialServiceType}) async {
var params = {
"SpecialServiceType": specialServiceId.toString(),
"SpecialServiceType": specialServiceType.toString(),
};
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(token: appState.getUser.data!.accessToken, (json) => GenericRespModel.fromJson(json), ApiConsts.vehicleAdsSpecialServicesGet, queryParameters: params);
List<SpecialServiceModel> vehicleAdsDuration = List.generate(adsGenericModel.data.length, (index) => SpecialServiceModel.fromJson(adsGenericModel.data[index]));

@ -108,16 +108,21 @@ class AppointmentRepoImp implements AppointmentRepo {
required List<String> serviceItemIdsForWorkshop,
}) async {
String t = appState.getUser.data!.accessToken ?? "";
var queryParameters = [
// {
// "appointmentType": 2,
// "ServiceItemIDs": serviceItemIdsForHome,
// },
{
var queryParameters = [];
if (serviceItemIdsForWorkshop.isNotEmpty) {
queryParameters.add({
"appointmentType": 1,
"ServiceItemIDs": serviceItemIdsForWorkshop,
}
];
});
}
if (serviceItemIdsForHome.isNotEmpty) {
queryParameters.add({
"appointmentType": 2,
"ServiceItemIDs": serviceItemIdsForHome,
});
}
GenericRespModel adsGenericModel = await apiClient.postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getServiceItemAppointmentScheduleSlots,

@ -8,6 +8,7 @@ import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/setting_utils_models/app_info_model.dart';
import 'package:mc_common_app/models/setting_utils_models/contact_infos_model.dart';
import 'package:mc_common_app/models/setting_utils_models/faqs_model.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
abstract class SettingOptionsRepo {
@ -16,6 +17,10 @@ abstract class SettingOptionsRepo {
Future<List<ContactInfoModel>> getAllContactInfos();
Future<List<AppInfoModel>> getAppInfoList();
Future<List<AppInfoModel>> getTermsAndConditions();
Future<void> appInvitationCreate({required int channelId});
}
class SettingOptionsRepoImp extends SettingOptionsRepo {
@ -24,12 +29,24 @@ class SettingOptionsRepoImp extends SettingOptionsRepo {
@override
Future<List<FAQsModel>> getAllFaqs() async {
int channel = 0;
if (AppState().currentAppType == AppType.provider) {
channel = 2;
} else {
channel = 3;
}
final params = {
"Channel": channel.toString(),
};
String token = appState.getUser.data!.accessToken ?? "";
GenericRespModel genericRespModel = await injector.get<ApiClient>().getJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getAllFAQs,
token: token,
queryParameters: params,
);
if (genericRespModel.messageStatus != 1 || genericRespModel.data == null) {
@ -66,10 +83,22 @@ class SettingOptionsRepoImp extends SettingOptionsRepo {
Future<List<AppInfoModel>> getAppInfoList() async {
String token = appState.getUser.data!.accessToken ?? "";
int channel = 0;
if (AppState().currentAppType == AppType.provider) {
channel = 2;
} else {
channel = 3;
}
final params = {
"Channel": channel.toString(),
};
GenericRespModel genericRespModel = await injector.get<ApiClient>().getJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getAppInfo,
token: token,
queryParameters: params,
);
if (genericRespModel.messageStatus != 1 || genericRespModel.data == null) {
@ -81,4 +110,63 @@ class SettingOptionsRepoImp extends SettingOptionsRepo {
return list;
}
@override
Future<List<AppInfoModel>> getTermsAndConditions() async {
String token = appState.getUser.data!.accessToken ?? "";
int channel = 0;
if (AppState().currentAppType == AppType.provider) {
channel = 2;
} else {
channel = 3;
}
final params = {
"Channel": channel.toString(),
};
GenericRespModel genericRespModel = await injector.get<ApiClient>().getJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getTermsAndConditions,
token: token,
queryParameters: params,
);
if (genericRespModel.messageStatus != 1 || genericRespModel.data == null) {
Utils.showToast(genericRespModel.message ?? LocaleKeys.somethingWrong.tr());
return [];
}
List<AppInfoModel> list = List.generate(genericRespModel.data.length, (index) => AppInfoModel.fromJson(genericRespModel.data[index], isForTermsAndCondition: true));
return list;
}
@override
Future<void> appInvitationCreate({required int channelId}) async {
String token = appState.getUser.data!.accessToken ?? "";
final params = {
"channelID": channelId.toString(),
"comments": "string",
};
if (AppState().currentAppType == AppType.provider) {
params.addAll({
"customerID": (appState.getUser.data!.userInfo!.customerId ?? "0").toString(),
});
} else {
params.addAll({
"providerID": (appState.getUser.data!.userInfo!.providerId ?? "0").toString(),
});
}
GenericRespModel genericRespModel = await injector.get<ApiClient>().postJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.createAppInvitation,
token: token,
params,
);
}
}

@ -52,7 +52,7 @@ class MyColors {
static const Color pendingColor = Colors.amber;
static const Color submittedColor = Colors.blue;
static const Color inProgressColor = Colors.deepOrange;
static const Color inProgressColor = Colors.indigo;
static const Color completedColor = Colors.green;
static const Color cancelledColor = Colors.red;
static const Color paidColor = Colors.teal;

@ -19,6 +19,20 @@ class AppEnums {
static const int shippingStatusEnumId = -2; // to get the Shipping Filter Enums
}
enum DashboardRouteEnum {
fromAdsPayment,
fromAdsSubmit,
none,
}
enum VehicleType {
car,
motorCycle,

@ -19,6 +19,7 @@ import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/widgets/loading_dialog.dart';
import 'package:share_plus/share_plus.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:url_launcher/url_launcher_string.dart';
@ -28,13 +29,7 @@ class Utils {
static bool get isLoading => _isLoadingVisible;
static void showToast(String message) {
Fluttertoast.showToast(msg: message,
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 2,
backgroundColor: Colors.black54,
textColor: Colors.white,
fontSize: 16.0);
Fluttertoast.showToast(msg: message, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 2, backgroundColor: Colors.black54, textColor: Colors.white, fontSize: 16.0);
}
static Future<void> openNumberViaCaller({required String phoneNumber}) async {
@ -49,6 +44,18 @@ class Utils {
}
}
static Future<void> openEmailViaEmailApp({required String emailAddress}) async {
Uri emailLaunchUrl = Uri.parse('mailto:$emailAddress');
if (await canLaunchUrl(emailLaunchUrl)) {
try {
await launchUrl(emailLaunchUrl);
} catch (e) {
await launchUrl(emailLaunchUrl);
}
}
}
static Future<void> openNumberViaWhatsApp({required String phoneNumber}) async {
final url = 'https://wa.me/$phoneNumber?text=';
@ -77,11 +84,7 @@ class Utils {
return "";
}
return ("${timeOfDay.hour
.toString()
.length == 1 ? "0" : ""}${timeOfDay.hour}:${timeOfDay.minute
.toString()
.length == 1 ? "0" : ""}${timeOfDay.minute}").toString();
return ("${timeOfDay.hour.toString().length == 1 ? "0" : ""}${timeOfDay.hour}:${timeOfDay.minute.toString().length == 1 ? "0" : ""}${timeOfDay.minute}").toString();
}
static dynamic getNotNullValue(List<dynamic> list, int index) {
@ -275,23 +278,20 @@ class Utils {
return MyColors.cancelledColor;
case RequestOfferStatusEnum.cancel:
return MyColors.redColor;
return MyColors.cancelledColor;
}
}
static String getNameByRequestOfferStatusEnum(RequestOfferStatusEnum requestOfferStatusEnum) {
switch (requestOfferStatusEnum) {
case RequestOfferStatusEnum.offer:
return "Pending";
return "Offer";
case RequestOfferStatusEnum.negotiate:
return "Negotiate";
case RequestOfferStatusEnum.accepted:
return "Accepted";
case RequestOfferStatusEnum.rejected:
return "Rejected";
case RequestOfferStatusEnum.cancel:
return "Cancelled";
}
@ -383,7 +383,6 @@ class Utils {
return Container(
decoration: BoxDecoration(
color: chipColor,
borderRadius: const BorderRadius.all(Radius.circular(200)),
),
padding: padding,
child: text.toText(fontSize: 10, color: textColor, letterSpacing: -0.50));
@ -522,7 +521,7 @@ class Utils {
border: Border.all(
width: w, //
color: color // <--- border width here
),
),
borderRadius: BorderRadius.circular(radius),
);
}
@ -545,7 +544,7 @@ class Utils {
border: Border.all(
width: 1, //
color: color // <--- border width here
),
),
borderRadius: BorderRadius.circular(radius),
);
}
@ -563,8 +562,7 @@ class Utils {
}
static String getAdsPaymentBrowserForm({required int paymentId, required int adId}) {
return '<html> <head></head><body><form id="paymentForm" action="${ApiConsts
.paymentWebViewUrl}" method="post"><input type="hidden" name="PaymentType" value="$paymentId"><input type="hidden" name="AdsID" value="$adId"></form><script type="text/javascript"> document.getElementById("paymentForm").submit(); </script></body></html>';
return '<html> <head></head><body><form id="paymentForm" action="${ApiConsts.paymentWebViewUrl}" method="post"><input type="hidden" name="PaymentType" value="$paymentId"><input type="hidden" name="AdsID" value="$adId"></form><script type="text/javascript"> document.getElementById("paymentForm").submit(); </script></body></html>';
}
// BOTTOM SHEETS
@ -589,6 +587,9 @@ class Utils {
}
static Widget buildStatusContainer(String text, {double marginAll = 8, double fontSize = 14}) {
if (text.isEmpty) {
return const SizedBox();
}
return Center(
child: text.toText(color: MyColors.lightTextColor, fontSize: fontSize),
).toContainer(
@ -611,4 +612,9 @@ class Utils {
}
}
}
static Future<ShareResult> shareAppInvitation() async {
ShareResult result = await Share.share(GlobalConsts.getAppInvitationLink(), subject: 'Join Mowater');
return result;
}
}

@ -108,7 +108,7 @@ class AdVM extends BaseVM {
vehicleAdsSpecialServices[index].isSelected = true;
}
specialServiceCards.add(specialServiceCard);
vehicleAdsSpecialServicesId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
selectedVehicleAdsSpecialServicesId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
adSpecialServiceDate = "";
notifyListeners();
}
@ -302,7 +302,7 @@ class AdVM extends BaseVM {
}
Future<void> getVehicleAdsSpecialServices() async {
vehicleAdsSpecialServices = await adsRepo.getSpecialServices(specialServiceId: 1);
vehicleAdsSpecialServices = await adsRepo.getSpecialServices(specialServiceType: 1);
notifyListeners();
}
@ -748,10 +748,10 @@ class AdVM extends BaseVM {
notifyListeners();
}
SelectionModel vehicleAdsSpecialServicesId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
SelectionModel selectedVehicleAdsSpecialServicesId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateVehicleAdsSpecialServicesId(SelectionModel id) async {
vehicleAdsSpecialServicesId = id;
void updateSelectedVehicleAdsSpecialServicesId(SelectionModel id) async {
selectedVehicleAdsSpecialServicesId = id;
// isFetchingLists = true;
// adSSTimeSlots.clear();
// vehicleAdsPhotoServiceDate = SelectionModel(selectedId: -1, selectedOption: "");
@ -1136,7 +1136,7 @@ class AdVM extends BaseVM {
resetValues();
updateIsExploreAds(false);
applyFilterOnMyAds(adPostStatusEnum: AdPostStatus.pendingForReview); //pending for review
navigateReplaceWithName(context, AppRoutes.dashboard);
navigateReplaceWithName(context, AppRoutes.dashboard, arguments: DashboardRouteEnum.fromAdsSubmit);
} catch (e) {
Utils.hideLoading(context);
Utils.showToast("Error: ${e.toString()}");
@ -1285,6 +1285,7 @@ class AdVM extends BaseVM {
vehicleAdsSpecialServices.clear();
currentProgressStep = AdCreationSteps.vehicleDetails;
vehicleTypeId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
vehicleModelId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
// vehicleAdDurationId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
vehicleBrandId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
vehicleModelYearId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");

@ -12,6 +12,7 @@ import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/models/appointments_models/appointment_slots.dart';
import 'package:mc_common_app/models/appointments_models/service_schedule_model.dart';
import 'package:mc_common_app/models/chat_models/chat_message_model.dart';
import 'package:mc_common_app/models/general_models/enums_model.dart';
import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
@ -163,6 +164,54 @@ class AppointmentsVM extends BaseVM {
navigateWithName(context, AppRoutes.paymentMethodsView, arguments: PaymentTypes.appointment);
}
OfferRequestCommentModel selectedCancelAppointmentReason = OfferRequestCommentModel(
index: 0,
isSelected: true,
title: LocaleKeys.changedMind.tr(),
);
List<OfferRequestCommentModel> cancelAppointmentReasonList = [
OfferRequestCommentModel(
index: 0,
isSelected: true,
title: LocaleKeys.wantToRescheduleAppointment.tr(),
),
OfferRequestCommentModel(
index: 1,
isSelected: false,
title: LocaleKeys.noNeedForService.tr(),
),
OfferRequestCommentModel(
index: 2,
isSelected: false,
title: LocaleKeys.testTheService.tr(),
),
OfferRequestCommentModel(
index: 3,
isSelected: false,
title: LocaleKeys.otherVar.tr(),
),
];
void updateSelectedCancelAppointmentReason(int index) {
for (var value in cancelAppointmentReasonList) {
value.isSelected = false;
}
selectedCancelAppointmentReason = cancelAppointmentReasonList[index];
cancelAppointmentReasonList[index].isSelected = true;
notifyListeners();
}
String cancelAppointmentDescription = "";
String cancelAppointmentDescriptionError = "";
void updateCancelAppointmentDescription(String value) {
cancelAppointmentDescription = value;
if (value.isNotEmpty) {
cancelAppointmentDescriptionError = "";
}
}
Future<void> onCancelAppointmentPressed({required BuildContext context, required AppointmentListModel appointmentListModel}) async {
Utils.showLoading(context);
try {
@ -498,6 +547,8 @@ class AppointmentsVM extends BaseVM {
serviceItemsFromApi[index].isUpdateOrSelected = selected;
serviceItemsFromApi[index].isHomeSelected = isHomeTapped;
log(" serviceItemsFromApi[index].isHomeSelected: ${serviceItemsFromApi[index].isHomeSelected}");
if (selected) {
selectedSubServicesCounter = selectedSubServicesCounter + 1;
selectSubServicesError = "";
@ -611,6 +662,7 @@ class AppointmentsVM extends BaseVM {
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
// TODO: It should be calculated from API
double totalKms = 15.3;
return InfoBottomSheet(
title: LocaleKeys.chargesBreakdown.tr().toText(fontSize: 24, isBold: true),
@ -625,7 +677,7 @@ class AppointmentsVM extends BaseVM {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
"${selectedService.serviceItems![index].name}".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
"${selectedService.serviceItems![index].price} SAR".toText(fontSize: 12, isBold: true),
"${selectedService.serviceItems![index].price} ${LocaleKeys.sar.tr()}".toText(fontSize: 12, isBold: true),
],
),
),
@ -633,7 +685,7 @@ class AppointmentsVM extends BaseVM {
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
"${selectedService.currentTotalServicePrice} SAR".toText(fontSize: 16, isBold: true),
"${selectedService.currentTotalServicePrice} ${LocaleKeys.sar.tr()}".toText(fontSize: 16, isBold: true),
],
),
if (selectedService.isHomeSelected) ...[
@ -650,7 +702,7 @@ class AppointmentsVM extends BaseVM {
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
"${selectedService.rangePricePerKm ?? 0 * totalKms} SAR".toText(fontSize: 16, isBold: true),
"${(double.parse(selectedService.rangePricePerKm!)) * totalKms} ${LocaleKeys.sar.tr()}".toText(fontSize: 16, isBold: true),
],
),
],
@ -662,7 +714,7 @@ class AppointmentsVM extends BaseVM {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
(selectedService.isHomeSelected ? "${(selectedService.currentTotalServicePrice) + (double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms)}" : "${selectedService.currentTotalServicePrice}")
(selectedService.isHomeSelected ? "${(selectedService.currentTotalServicePrice) + ((double.parse((selectedService.rangePricePerKm ?? "0.0")) * totalKms))}" : "${selectedService.currentTotalServicePrice}")
.toText(fontSize: 29, isBold: true),
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
@ -718,6 +770,8 @@ class AppointmentsVM extends BaseVM {
List<String> serviceItemIdsForHome = [];
List<String> serviceItemIdsForWorkshop = [];
for (var serviceItem in allSelectedItemsInAppointments) {
log("homeselcted for : ${serviceItem.isHomeSelected}");
if (serviceItem.isHomeSelected!) {
serviceItemIdsForHome.add(serviceItem.id!.toString());
} else {
@ -1098,22 +1152,14 @@ class AppointmentsVM extends BaseVM {
setState(ViewState.idle);
}
Future<void> fetchAllCategories(String countryCode) async {
Future<void> fetchAllCategories() async {
if (categoryDropList.isNotEmpty) return;
categoryDropList.clear();
setOnlyState(ViewState.busy);
Category category = await branchRepo.fetchBranchCategory();
category.data?.forEach((element) {
categoryDropList.add(
DropValue(
element.id ?? 0,
((element.categoryName!.isEmpty
? "N/A"
: countryCode == "SA"
? element.categoryNameN
: element.categoryName) ??
"N/A"),
""),
DropValue(element.id ?? 0, ((element.categoryName!.isEmpty ? "N/A" : element.categoryName) ?? "N/A"), ""),
);
});
setState(ViewState.idle);
@ -1139,7 +1185,7 @@ class AppointmentsVM extends BaseVM {
Future<void> populateDataForBranchesFilter() async {
await fetchAllProviders(); // saudi arabia
await fetchAllCategories("SA"); // saudi arabia
await fetchAllCategories(); // saudi arabia
await fetchAllServices(); // saudi arabia
updateBranchFilterCurrentDistance(25.0);
}
@ -1231,9 +1277,9 @@ class AppointmentsVM extends BaseVM {
}
Future<void> populateDataForAppointmentsFilter() async {
await fetchAllProviders(); // saudi arabia
await fetchAllCategories("SA"); // saudi arabia
await fetchAllServices(); // saudi arabia
await fetchAllProviders();
await fetchAllCategories();
await fetchAllServices();
}
int appointmentFiltersCounter = 0;

@ -103,12 +103,6 @@ class ChatVM extends ChangeNotifier {
),
];
OfferRequestCommentModel selectedOfferRequestCommentModel = OfferRequestCommentModel(
index: 0,
isSelected: true,
title: LocaleKeys.changedMind.tr(),
);
void updateSelectionInOfferRejectModelList(int index) {
for (var value in offerRejectModelList) {
value.isSelected = false;
@ -118,6 +112,12 @@ class ChatVM extends ChangeNotifier {
notifyListeners();
}
OfferRequestCommentModel selectedOfferRequestCommentModel = OfferRequestCommentModel(
index: 0,
isSelected: true,
title: LocaleKeys.changedMind.tr(),
);
String rejectOfferDescription = "";
String rejectOfferDescriptionError = "";
@ -154,8 +154,6 @@ class ChatVM extends ChangeNotifier {
if (currentMessage.chatMessageTypeEnum == ChatMessageTypeEnum.offer) {
for (var chatMessage in serviceProviderOffersList[providerIndex].chatMessages!) {
if (chatMessage.chatMessageTypeEnum == ChatMessageTypeEnum.offer && chatMessage.reqOffer!.id == currentMessage.reqOffer!.id) {
logger.i("chatMessage reqOfferID: ${chatMessage.reqOffer!.id.toString()}");
logger.i("currentMessage reqOfferID: ${currentMessage.reqOffer!.id.toString()}");
chatMessage.reqOffer!.requestOfferStatusEnum = currentMessage.reqOffer!.requestOfferStatusEnum;
}
}
@ -253,6 +251,7 @@ class ChatVM extends ChangeNotifier {
required String serviceItemName,
required int manufacturedById,
required String manufacturedOn,
required List<dynamic> offerImages,
required BuildContext context,
}) async {
if (hubConnection == null || hubConnection!.state != HubConnectionState.connected) {
@ -272,6 +271,7 @@ class ChatVM extends ChangeNotifier {
"RequestID": requestId,
"Price": double.parse(offerPrice),
"ServiceItem": serviceItemName,
"ReqOfferImages": offerImages,
"OfferedItemCreatedBy": manufacturedById, // TODO: The ID should be used from the manufacturer database
// "OfferedItemCreatedOn": manufacturedOn, // TODO: This should be in String on Server, Right now it is in DateTime
"ServiceProviderID": providerId,
@ -464,6 +464,7 @@ class ChatVM extends ChangeNotifier {
}
if (unreadMessageIds.isNotEmpty) {
log("unreadMessageIds: ${unreadMessageIds.toString()}");
await markMessagesAsRead(context, unreadMessageIds, ChatTypeEnum.requestOffer);
}
Utils.hideLoading(context);

@ -1,3 +1,4 @@
import 'dart:developer';
import 'dart:io';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
@ -5,6 +6,7 @@ import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/models/user_models/image_response.dart';
import 'package:mc_common_app/repositories/user_repo.dart';
import 'package:mc_common_app/services/common_services.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
@ -56,7 +58,8 @@ class DashboardVmCustomer extends BaseVM {
}
}
Future<void> onRefresh(BuildContext context) async {
Future<void> onRefresh(BuildContext context, {DashboardRouteEnum dashboardRouteEnum = DashboardRouteEnum.none}) async {
log("onRefresh dashboardRouteEnum: $dashboardRouteEnum");
AdVM adVM = Provider.of<AdVM>(context, listen: false);
AppointmentsVM appointmentsVM = Provider.of<AppointmentsVM>(context, listen: false);
RequestsVM requestsVM = Provider.of<RequestsVM>(context, listen: false);
@ -67,9 +70,13 @@ class DashboardVmCustomer extends BaseVM {
requestsVM.populateDataForRequestsFilter();
await appointmentsVM.getMyAppointmentsForCustomer();
await appointmentsVM.applyFilterOnBranches(index: 0); // to get all branches!
await appointmentsVM.getMyRecentBranches(); // to get my recent branches!
await adVM.getMyAds();
await adVM.getExploreAds();
await appointmentsVM.getMyRecentBranches(); // to get my recent branches
if (dashboardRouteEnum != DashboardRouteEnum.fromAdsPayment && dashboardRouteEnum != DashboardRouteEnum.fromAdsSubmit) {
await adVM.getMyAds();
await adVM.getExploreAds();
}
await requestsVM.getRequests();
await adVM.getVehicleTypes();
await adVM.getVehicleAdsDuration();

@ -15,7 +15,6 @@ import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/shipping_management_view_model.dart';
import 'package:mc_common_app/widgets/common_widgets/add_phone_num_wiget.dart';
import 'package:provider/provider.dart';
import 'package:mc_common_app/utils/location/Location.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
@ -71,29 +70,35 @@ class DashboardVMProvider extends BaseVM {
return await userRepo.updateUserImage(image);
}
Future<void> onRefresh(BuildContext context) async {
Future<void> onRefresh(BuildContext context, { DashboardRouteEnum dashboardRouteEnum = DashboardRouteEnum.none }) async {
final requestsVM = context.read<RequestsVM>();
final chatVM = context.read<ChatVM>();
final appointmentVM = context.read<AppointmentsVM>();
final shippingManagementVM = context.read<ShippingManagementVM>();
final serviceVM = context.read<ServiceVM>();
final adVm = context.read<AdVM>();
final adVM = context.read<AdVM>();
final subscriptionsVM = context.read<SubscriptionsVM>();
requestsVM.populateDataForRequestsFilter();
appointmentVM.populateAppointmentsFilterList();
shippingManagementVM.populateShippingRequestFilterList();
await serviceVM.getBranchAndServices();
await appointmentVM.getMyAppointmentsForProvider({"ServiceProviderID": injector.get<AppState>().getUser.data?.userInfo?.providerId.toString() ?? "0"});
adVm.populateAdsFilterList();
await appointmentVM.getMyAppointmentsForProvider({"ServiceProviderID": injector
.get<AppState>()
.getUser
.data
?.userInfo
?.providerId
.toString() ?? "0"});
adVM.populateAdsFilterList();
await subscriptionsVM.getSubscriptionBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "", true);
await chatVM.buildHubConnection(context);
await adVm.getMyAds();
await adVm.getExploreAds();
await adVm.getVehicleTypes();
await adVm.getVehicleAdsDuration();
if (dashboardRouteEnum != DashboardRouteEnum.fromAdsPayment && dashboardRouteEnum != DashboardRouteEnum.fromAdsSubmit) {
await adVM.getMyAds();
await adVM.getExploreAds();
}
await adVM.getVehicleTypes();
await adVM.getVehicleAdsDuration();
await requestsVM.getRequests();
// await subscriptionsVM.getMySubscriptionsBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "");
// await subscriptionsVM.getMySubscriptionsBySP(AppState().getUser.data?.userInfo?.providerId.toString() ?? "");
}
void checkUserSubscription(SubscriptionActionTypeEnum actionType, BuildContext context, {required Function() callback}) async {
@ -112,29 +117,25 @@ class DashboardVMProvider extends BaseVM {
void performCheckOnBranches(BuildContext context) async {
if (AppState().getproviderSubscription.isNotEmpty && AppState().getproviderSubscription.first.branchesRemaining! > 0) {
logger.d(AppState().getproviderSubscription.first.toJson());
await navigateWithName(context, AppRoutes.defineBranch);
} else {
Utils.showToast("Upgrade your subscription to add more Branches.");
Utils.showToast(LocaleKeys.upgradeBranches.tr());
}
}
void performCheckOnAds(BuildContext context) async {
//adsRemaining
if (AppState().getproviderSubscription.isNotEmpty && AppState().getproviderSubscription.first.adsRemaining! > 0) {
logger.d(AppState().getproviderSubscription.first.toJson());
await navigateWithName(context, AppRoutes.defineBranch);
} else {
Utils.showToast("Upgrade your subscription to add more Ads.");
Utils.showToast(LocaleKeys.upgradeAds.tr());
}
}
void performCheckOnUsers(BuildContext context, Function() callBack) async {
if (AppState().getproviderSubscription.isNotEmpty && AppState().getproviderSubscription.first.subUsersRemaining! > 0) {
logger.d(AppState().getproviderSubscription.first.toJson());
showMyBottomSheet(context, isDismissible: false, child: const AddPhoneNumWidget(), callBackFunc: callBack);
} else {
Utils.showToast("Upgrade your subscription to add more Sub Users.");
Utils.showToast(LocaleKeys.upgradeSubUsers.tr());
}
}
}

@ -10,10 +10,9 @@ import 'package:mc_common_app/services/payments_service.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/dashboard_view_model_customer.dart';
import 'package:mc_common_app/view_models/dashboard_view_model_provider.dart';
import 'package:mc_common_app/view_models/subscriptions_view_model.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
@ -192,12 +191,15 @@ class PaymentVM extends ChangeNotifier {
}
void onAdsPaymentSuccess(BuildContext context) {
context.read<AdVM>().updateIsExploreAds(false);
if (AppState().currentAppType == AppType.provider) {
context.read<DashboardVMProvider>().onNavbarTapped(3);
context.read<AdVM>().applyFilterOnMyAds(adPostStatusEnum: AdPostStatus.active);
} else {
context.read<DashboardVmCustomer>().onNavbarTapped(3);
context.read<AdVM>().applyFilterOnMyAds(adPostStatusEnum: AdPostStatus.pendingForPost);
}
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard);
navigateReplaceWithNameUntilRoute(context, AppRoutes.dashboard, arguments: DashboardRouteEnum.fromAdsPayment);
}
void onSubscriptionPaymentSuccess(BuildContext context) {

@ -796,6 +796,13 @@ class RequestsVM extends BaseVM {
serviceItem = value;
}
bool isDeliveryAvailableStatus = false;
void updateIsDeliveryAvailableStatus(bool value) {
isDeliveryAvailableStatus = value;
notifyListeners();
}
String serviceItemCreatedOn = "";
void updateServiceItemCreatedOn(String value) {
@ -807,7 +814,7 @@ class RequestsVM extends BaseVM {
void updateOfferDescription(String value) {
offerDescription = value;
if (value.isNotEmpty) {
if (value.isNotEmpty || value.length <= 5) {
offerDescriptionError = "";
}
}
@ -885,6 +892,7 @@ class RequestsVM extends BaseVM {
serviceItem = "";
serviceItemCreatedOn = "";
itemManufacturer = "";
pickedVehicleImages.clear();
notifyListeners();
}
@ -903,6 +911,14 @@ class RequestsVM extends BaseVM {
}) async {
if (isSendOfferValidated()) {
final chatVM = context.read<ChatVM>();
Utils.showLoading(context);
List<RequestPostingImages> vehicleImages = await getVehiclePostingImageList();
List offerImages = [];
vehicleImages.forEach((element) {
offerImages.add(element.toJson());
});
bool status = await chatVM.onOfferSendForRequest(
receiverId: receiverId,
chatMessageType: ChatMessageTypeEnum.offer,
@ -912,52 +928,58 @@ class RequestsVM extends BaseVM {
manufacturedById: manufacturedById,
manufacturedOn: manufacturedOn,
serviceItemName: serviceItemName,
offerImages: offerImages,
context: context,
);
Utils.hideLoading(context);
log("status from onOfferSendForRequest: $status");
if (status) {
final senderName = AppState().getUser.data!.userInfo!.firstName;
final senderId = AppState().getUser.data!.userInfo!.userId;
resetSendOfferBottomSheet();
Navigator.pop(context);
ChatMessageModel chatMessageModel = ChatMessageModel(
isMyMessage: true,
chatText: message,
messageType: ChatMessageTypeEnum.offer.getIdFromChatMessageTypeEnum(),
senderName: senderName,
senderUserID: senderId,
receiverUserID: receiverId,
chatMessageTypeEnum: ChatMessageTypeEnum.offer,
requestID: requestModel.id,
if (!status) {
Utils.showToast(LocaleKeys.somethingWrong.tr());
return;
}
final senderName = AppState().getUser.data!.userInfo!.firstName;
final senderId = AppState().getUser.data!.userInfo!.userId;
resetSendOfferBottomSheet();
Navigator.pop(context);
ChatMessageModel chatMessageModel = ChatMessageModel(
isMyMessage: true,
chatText: message,
messageType: ChatMessageTypeEnum.offer.getIdFromChatMessageTypeEnum(),
senderName: senderName,
senderUserID: senderId,
receiverUserID: receiverId,
chatMessageTypeEnum: ChatMessageTypeEnum.offer,
requestID: requestModel.id,
offerStatus: RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
reqOffer: ReqOffer(
offerStatus: RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
reqOffer: ReqOffer(
offerStatus: RequestOfferStatusEnum.offer.getIdFromRequestOfferStatusEnum(),
requestID: requestModel.id,
price: double.parse(offerPrice),
manufacturedById: manufacturedById,
manufacturedOn: manufacturedOn,
serviceItemName: serviceItemName,
requestOfferStatusEnum: RequestOfferStatusEnum.offer,
comment: message,
offerStatusText: "",
),
requestID: requestModel.id,
price: double.parse(offerPrice),
manufacturedById: manufacturedById,
manufacturedOn: manufacturedOn,
serviceItemName: serviceItemName,
requestOfferStatusEnum: RequestOfferStatusEnum.offer,
comment: message,
offerStatusText: "",
),
);
context.read<ChatVM>().onNewMessageReceivedForRequestOffer(messages: [chatMessageModel], requestsVM: this, isMyOwnOffer: true);
if (!isFromChatScreen) {
ChatViewArgumentsForRequest chatViewArgumentsForRequest = ChatViewArgumentsForRequest(
chatTypeEnum: ChatTypeEnum.requestOffer,
requestId: requestModel.id,
receiverId: requestModel.customerID,
senderId: senderId ?? "",
requestIndex: requestIndex,
providerIndex: -1,
requestModel: requestModel,
);
context.read<ChatVM>().onNewMessageReceivedForRequestOffer(messages: [chatMessageModel], requestsVM: this, isMyOwnOffer: true);
if (!isFromChatScreen) {
ChatViewArgumentsForRequest chatViewArgumentsForRequest = ChatViewArgumentsForRequest(
chatTypeEnum: ChatTypeEnum.requestOffer,
requestId: requestModel.id,
receiverId: requestModel.customerID,
senderId: senderId ?? "",
requestIndex: requestIndex,
providerIndex: -1,
requestModel: requestModel,
);
ChatViewArguments chatViewArguments = ChatViewArguments(chatTypeEnum: ChatTypeEnum.requestOffer, chatViewArgumentsForRequest: chatViewArgumentsForRequest);
navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments);
}
ChatViewArguments chatViewArguments = ChatViewArguments(chatTypeEnum: ChatTypeEnum.requestOffer, chatViewArgumentsForRequest: chatViewArgumentsForRequest);
navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments);
}
}
}

@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/models/setting_utils_models/app_info_model.dart';
import 'package:mc_common_app/models/setting_utils_models/contact_infos_model.dart';
@ -6,6 +7,7 @@ import 'package:mc_common_app/repositories/setting_options_repo.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
import 'package:share_plus/share_plus.dart';
class SettingOptionsVM extends BaseVM {
final SettingOptionsRepo settingOptionsRepo;
@ -56,4 +58,36 @@ class SettingOptionsVM extends BaseVM {
setState(ViewState.idle);
}
}
List<AppInfoModel> termsAndConditionsList = [];
Future<void> getTermsAndConditions() async {
setState(ViewState.busy);
try {
termsAndConditionsList = await settingOptionsRepo.getTermsAndConditions();
setState(ViewState.idle);
notifyListeners();
} catch (e) {
logger.i(e.toString());
Utils.showToast(e.toString());
setState(ViewState.idle);
}
}
Future<void> appInvitationCreate({required BuildContext context, required int channelId}) async {
ShareResult result = await Utils.shareAppInvitation();
if (result.status != ShareResultStatus.success) {
return;
}
Utils.showLoading(context);
try {
await settingOptionsRepo.appInvitationCreate(channelId: channelId);
Utils.hideLoading(context);
} catch (e) {
logger.i(e.toString());
Utils.showToast(e.toString());
Utils.hideLoading(context);
}
}
}

@ -282,7 +282,7 @@ class AdDuration extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(LocaleKeys.description.tr() + ": ").toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
("${LocaleKeys.description.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
(specialServicesCard.description ?? "").toText(fontSize: 12, isBold: true).expand(),
],
),

@ -283,7 +283,7 @@ class VehicleDetails extends StatelessWidget {
).paddingOnly(right: 10)
],
if (adVM.pickedPostingImages.isNotEmpty) ...[
16.height,
8.height,
PickedFilesContainer(
pickedFiles: adVM.pickedPostingImages,
onCrossPressedPrimary: adVM.removeImageFromList,

@ -15,6 +15,7 @@ import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/payment_view_model.dart';
import 'package:mc_common_app/views/advertisement/ads_detail_view/components.dart';
import 'package:mc_common_app/views/advertisement/bottom_sheets/ad_duration_selection_sheet.dart';
import 'package:mc_common_app/views/advertisement/bottom_sheets/ads_damage_part_pictures_sheet.dart';
import 'package:mc_common_app/views/advertisement/components/ads_images_corousel_widget.dart';
import 'package:mc_common_app/widgets/bottom_sheet.dart';
@ -252,34 +253,79 @@ class _AdsDetailViewState extends State<AdsDetailView> {
}).toWhiteContainer(width: double.infinity, allPading: 12);
}
Future<void> onExtendAdPressed() async {
final AdVM adVM = context.read<AdVM>();
return actionConfirmationBottomSheet(
context: context,
title: LocaleKeys.updateAdDetails.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
subtitle: LocaleKeys.durationExtendingAd.tr(),
actionButtonYes: Expanded(
child: ShowFillButton(
maxHeight: 55,
title: LocaleKeys.yes.tr(),
fontSize: 15,
onPressed: () async {
Utils.showLoading(context);
await adVM.getVehicleTypes();
await adVM.getVehicleBrandsByVehicleTypeId(vehicleIdForEditAd: widget.adDetails.vehicle!.vehicleType ?? -1);
Utils.hideLoading(context);
adVM.onEditUpdateAdPressed(context: context, previousDetails: widget.adDetails, isFromExtendAd: true);
},
),
),
actionButtonNo: Expanded(
child: ShowFillButton(
maxHeight: 55,
isFilled: false,
borderColor: MyColors.darkPrimaryColor,
title: LocaleKeys.no.tr(),
txtColor: MyColors.darkPrimaryColor,
fontSize: 15,
onPressed: () {
adVM.updateSelectionVehicleTypeId(
SelectionModel(selectedId: widget.adDetails.vehicle!.vehicleType!, selectedOption: (widget.adDetails.vehicle!.vehicleType!).toVehicleTypeString(), errorValue: ""),
);
showMyBottomSheet(context, child: AdDurationSelectionSheet(isFromExtendAd: true, isUpdateAdSelected: false, adsID: widget.adDetails.id ?? -1));
},
),
),
);
}
Widget buildAdStartEndDates() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
("${LocaleKeys.startDate.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
widget.adDetails.startdate != null
? DateHelper.formatAsDayMonthYear(DateTime.parse(widget.adDetails.startdate!)).toText(
fontSize: 10,
)
: const SizedBox(),
Row(
children: [
("${LocaleKeys.startDate.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
widget.adDetails.startdate != null
? DateHelper.formatAsDayMonthYear(DateTime.parse(widget.adDetails.startdate!)).toText(
fontSize: 10,
)
: const SizedBox(),
],
),
Row(
children: [
("${LocaleKeys.endDate.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
widget.adDetails.enddate != null ? DateHelper.formatAsDayMonthYear(DateTime.parse(widget.adDetails.enddate!)).toText(fontSize: 10) : const SizedBox(),
],
),
],
),
3.height,
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
("${LocaleKeys.endDate.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
widget.adDetails.enddate != null
? DateHelper.formatAsDayMonthYear(DateTime.parse(widget.adDetails.enddate!)).toText(
fontSize: 10,
)
: const SizedBox(),
(LocaleKeys.extendAd.tr()).toText(fontSize: 12, color: MyColors.darkPrimaryColor, isUnderLine: true).onPress(() async => await onExtendAdPressed()),
],
),
)
],
).paddingOnly(top: 5, bottom: 5).onPress(() {
showMyBottomSheet(context, child: AdDamagePartPicturesSheet(adDamageReportList: widget.adDetails.vehicle!.damagereport ?? []));
}).toWhiteContainer(width: double.infinity, allPading: 12);
).paddingOnly(top: 5, bottom: 2).toWhiteContainer(width: double.infinity, allPading: 12);
}
@override

@ -5,6 +5,7 @@ import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/advertisment_models/vehicle_details_models.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/utils/utils.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/time_slots.dart';
@ -149,7 +150,7 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget {
const BottomSheetAdSpecialServiceContent({Key? key}) : super(key: key);
bool isButtonTappable(AdVM adVM) {
bool status = (adVM.vehicleAdsSpecialServicesId.selectedId != -1) && (adVM.vehicleAdsSpecialServicesId.selectedOption != "");
bool status = (adVM.selectedVehicleAdsSpecialServicesId.selectedId != -1) && (adVM.selectedVehicleAdsSpecialServicesId.selectedOption != "");
if (status) {
return true;
}
@ -157,21 +158,16 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget {
}
Widget descriptionCard({required String description}) {
return Container(
height: 100,
decoration: BoxDecoration(color: MyColors.greyButtonColor, border: Border.all(width: 2, color: MyColors.greyAddBorderColor)),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: description.toText(
fontSize: 15,
color: MyColors.lightTextColor,
),
),
],
),
);
if (description.isEmpty) {
return const SizedBox();
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
("${LocaleKeys.description.tr()}:").toText(fontSize: 14),
description.toText(color: MyColors.lightTextColor),
],
).paddingOnly(left: 2);
}
@override
@ -179,7 +175,7 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget {
return Consumer(
builder: (BuildContext context, AdVM adVM, Widget? child) {
return SizedBox(
height: MediaQuery.of(context).size.height * 0.85,
height: MediaQuery.of(context).size.height * 0.7,
child: Column(
children: [
Container(
@ -204,19 +200,19 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget {
}
}
return DropdownField(
(DropValue value) => adVM.updateVehicleAdsSpecialServicesId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)),
(DropValue value) => adVM.updateSelectedVehicleAdsSpecialServicesId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)),
list: vehicleAdsSpecialServices,
hint: LocaleKeys.selectService.tr(),
dropdownValue: adVM.vehicleAdsSpecialServicesId.selectedId != -1 ? DropValue(adVM.vehicleAdsSpecialServicesId.selectedId, adVM.vehicleAdsSpecialServicesId.selectedOption, "") : null,
dropdownValue: adVM.selectedVehicleAdsSpecialServicesId.selectedId != -1 ? DropValue(adVM.selectedVehicleAdsSpecialServicesId.selectedId, adVM.selectedVehicleAdsSpecialServicesId.selectedOption, "") : null,
);
},
),
if (adVM.vehicleAdsSpecialServicesId.selectedId != -1) ...[
if (adVM.selectedVehicleAdsSpecialServicesId.selectedId != -1) ...[
if (adVM.isFetchingLists) ...[
Center(child: const CircularProgressIndicator().paddingAll(20)),
] else ...[
8.height,
if ((adVM.vehicleAdsSpecialServicesId.selectedId == 1 && adVM.ssPhotoScheduleModel != null)) ...[
if ((adVM.selectedVehicleAdsSpecialServicesId.selectedId == 1 && adVM.ssPhotoScheduleModel != null)) ...[
// Builder(
// builder: (context) {
// List<DropValue> vehicleAdsSpecialServiceDates = adVM.populateScheduleDatesForAdPhotoService();
@ -239,7 +235,7 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget {
// },
// ),
// 22.height,
] else if ((adVM.vehicleAdsSpecialServicesId.selectedId == 3 && adVM.ssCarCheckScheduleModel != null)) ...[
] else if ((adVM.selectedVehicleAdsSpecialServicesId.selectedId == 3 && adVM.ssCarCheckScheduleModel != null)) ...[
// Builder(
// builder: (context) {
// List<DropValue> vehicleAdsSpecialServiceDates = adVM.populateScheduleDatesForAdCarCheckService();
@ -263,9 +259,9 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget {
// ),
// 22.height,
],
if (adVM.vehicleAdsSpecialServicesId.selectedId != 3 && adVM.vehicleAdsSpecialServicesId.selectedId != 1) ...[
if (adVM.selectedVehicleAdsSpecialServicesId.selectedId != 3 && adVM.selectedVehicleAdsSpecialServicesId.selectedId != 1) ...[
descriptionCard(
description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.vehicleAdsSpecialServicesId.selectedId).description ?? "Some Dummy Service Description!!",
description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.selectedVehicleAdsSpecialServicesId.selectedId).description ?? "",
),
],
if (adVM.adSSTimeSlots.isNotEmpty) ...[
@ -281,7 +277,7 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
adVM.vehicleAdsSpecialServicesId.itemPrice.toText(fontSize: 20, isBold: true),
adVM.selectedVehicleAdsSpecialServicesId.itemPrice.toText(fontSize: 20, isBold: true),
SizedBox(width: 1.w),
LocaleKeys.sar.tr().toText(fontSize: 12, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 2),
],
@ -294,7 +290,7 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget {
SizedBox(
width: double.infinity,
child: ShowFillButton(
backgroundColor: !isButtonTappable(adVM) ? MyColors.lightTextColor.withOpacity(0.6) : MyColors.primaryColor,
backgroundColor: !isButtonTappable(adVM) ? MyColors.lightTextColor.withOpacity(0.6) : MyColors.darkPrimaryColor,
title: LocaleKeys.addService.tr(),
onPressed: () {
if (!isButtonTappable(adVM)) {
@ -304,8 +300,8 @@ class BottomSheetAdSpecialServiceContent extends StatelessWidget {
adVM.addNewSpecialServiceCard(
specialServiceCard: SpecialServiceCard(
serviceSelectedId: adVM.vehicleAdsSpecialServicesId,
description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.vehicleAdsSpecialServicesId.selectedId).description ?? "",
serviceSelectedId: adVM.selectedVehicleAdsSpecialServicesId,
description: adVM.vehicleAdsSpecialServices.firstWhere((element) => element.id == adVM.selectedVehicleAdsSpecialServicesId.selectedId).description ?? "",
duration: "",
serviceDate: "",
serviceDateError: "",

@ -4,16 +4,21 @@ 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/appointment_list_model.dart';
import 'package:mc_common_app/models/chat_models/chat_message_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/dialogs_and_bottomsheets.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/checkbox_with_title_desc.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/common_widgets/card_button_with_icon.dart';
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';
import 'package:sizer/sizer.dart';
@ -81,7 +86,7 @@ class AppointmentDetailView extends StatelessWidget {
alignment: Alignment.bottomCenter,
child: Row(
children: [
getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => appointmentCancelConfirmationSheet(context), text: LocaleKeys.cancel.tr()),
getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => buildCancelAppointmentReasonsBottomSheet(context: context), text: LocaleKeys.cancel.tr()),
12.width,
getBaseActionButtonWidget(
color: MyColors.greenColor,
@ -97,7 +102,7 @@ class AppointmentDetailView extends StatelessWidget {
alignment: Alignment.bottomCenter,
child: Row(
children: [
getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => appointmentCancelConfirmationSheet(context), text: "Cancel"),
getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => buildCancelAppointmentReasonsBottomSheet(context: context), text: LocaleKeys.cancel.tr()),
],
),
);
@ -128,7 +133,7 @@ class AppointmentDetailView extends StatelessWidget {
alignment: Alignment.bottomCenter,
child: Row(
children: [
getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => appointmentCancelConfirmationSheet(context), text: LocaleKeys.cancel.tr()),
getBaseActionButtonWidget(color: MyColors.redColor, onPressed: () => buildCancelAppointmentReasonsBottomSheet(context: context), text: LocaleKeys.cancel.tr()),
12.width,
getBaseActionButtonWidget(
color: MyColors.greenColor,
@ -177,6 +182,77 @@ class AppointmentDetailView extends StatelessWidget {
);
}
Future buildCancelAppointmentReasonsBottomSheet({required BuildContext context}) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
return Consumer(builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
return InfoBottomSheet(
title: LocaleKeys.pleaseSpecify.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
12.height,
ListView.separated(
shrinkWrap: true,
itemCount: appointmentsVM.cancelAppointmentReasonList.length,
separatorBuilder: (BuildContext context, int index) {
return const Divider(thickness: 0.5);
},
itemBuilder: (BuildContext context, int index) {
OfferRequestCommentModel offerRequestCommentModel = appointmentsVM.cancelAppointmentReasonList[index];
return CircleCheckBoxWithTitle(
isChecked: offerRequestCommentModel.isSelected ?? false,
title: '${offerRequestCommentModel.title}',
onSelected: () {
appointmentsVM.updateSelectedCancelAppointmentReason(index);
},
selectedColor: MyColors.darkPrimaryColor,
);
},
),
if (appointmentsVM.selectedCancelAppointmentReason.index == appointmentsVM.cancelAppointmentReasonList.length - 1) ...[
// comparing if the "other" is selected
12.height,
TxtField(
maxLines: 5,
value: appointmentsVM.cancelAppointmentDescription,
errorValue: appointmentsVM.cancelAppointmentDescriptionError,
keyboardType: TextInputType.text,
hint: LocaleKeys.description.tr(),
onChanged: (v) => appointmentsVM.updateCancelAppointmentDescription(v),
),
],
],
),
25.height,
ShowFillButton(
title: LocaleKeys.submit.tr(),
onPressed: () {
if (appointmentsVM.selectedCancelAppointmentReason.index == 0) {
appointmentsVM.onRescheduleAppointmentPressed(context: context, appointmentListModel: appointmentListModel);
} else {
context.read<AppointmentsVM>().onCancelAppointmentPressed(context: context, appointmentListModel: appointmentListModel);
}
},
maxWidth: double.infinity,
),
19.height,
],
),
));
});
},
);
}
@override
Widget build(BuildContext context) {
AppointmentsVM appointmentsVM = context.read<AppointmentsVM>();

@ -96,6 +96,7 @@ class _AppointmentsFilterViewState extends State<AppointmentsFilterView> {
children: [
SizedBox(
height: 5.h,
width: 5.h,
child: const CircularProgressIndicator(),
),
],

@ -14,6 +14,7 @@ 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';
import 'package:sizer/sizer.dart';
class ScreenArgumentsForAppointmentDetailPage {
final int routeFlag; // 1 = coming from create appointment || 2 = coming from reschedule appointment
@ -63,7 +64,8 @@ class BookAppointmentSchedulesView extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(LocaleKeys.serviceLocation.tr()).toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
(scheduleData.appointmentTypeEnum == AppointmentTypeEnum.home ? LocaleKeys.home.tr() : LocaleKeys.workshop.tr()).toText(fontSize: 12, isBold: true).expand(),
2.width,
(scheduleData.appointmentTypeEnum == AppointmentTypeEnum.home ? LocaleKeys.customerLocation.tr() : LocaleKeys.companyLocation.tr()).toText(fontSize: 12, isBold: true).expand(),
],
),
Column(
@ -110,9 +112,7 @@ class BookAppointmentSchedulesView extends StatelessWidget {
SizedBox(
width: double.infinity,
child: BuildTimeSlots(
timeSlots: appointmentsVM.serviceAppointmentScheduleList[scheduleIndex]
.customTimeDateSlotList![appointmentsVM.serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex!].availableSlots ??
[],
timeSlots: appointmentsVM.serviceAppointmentScheduleList[scheduleIndex].customTimeDateSlotList![appointmentsVM.serviceAppointmentScheduleList[scheduleIndex].selectedDateIndex!].availableSlots ?? [],
onPressed: (slotIndex) {
appointmentsVM.updateSelectedAppointmentSlotByDate(scheduleIndex: scheduleIndex, slotIndex: slotIndex);
},

@ -67,17 +67,17 @@ class BookAppointmentServicesView extends StatelessWidget {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${itemData.name}: ".toText(fontSize: 13, color: MyColors.lightTextColor, isBold: true),
"${itemData.name}: ".toText(fontSize: 13, color: MyColors.lightTextColor),
("${itemData.price}").toText(fontSize: 13, isBold: true).expand(),
],
);
}),
),
8.height,
// 8.height,
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(LocaleKeys.serviceLocation.tr()).toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
(LocaleKeys.serviceLocation.tr()).toText(fontSize: 12, color: MyColors.lightTextColor),
4.width,
(serviceData.isHomeSelected ? serviceData.homeLocation : LocaleKeys.workshop.tr()).toText(fontSize: 12, isBold: true).expand(),
],
@ -86,12 +86,12 @@ class BookAppointmentServicesView extends StatelessWidget {
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
((appointmentsVM.servicesInCurrentAppointment[serviceIndex].currentTotalServicePrice).toString()).toText(fontSize: 32, isBold: true),
((serviceData.currentTotalServicePrice).toString()).toText(fontSize: 32, isBold: true),
2.width,
LocaleKeys.sar.tr().toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
const Icon(Icons.arrow_drop_down, size: 30)
],
).onPress(() => appointmentsVM.priceBreakDownClicked(context, appointmentsVM.servicesInCurrentAppointment[serviceIndex])),
).onPress(() => appointmentsVM.priceBreakDownClicked(context, serviceData)),
],
],
).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10));

@ -7,6 +7,7 @@ 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/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/views/appointments/widgets/service_item_with_price_checkbox.dart';
@ -63,31 +64,32 @@ class BookAppointmentsItemView extends StatelessWidget {
const Divider(),
],
).horPaddingMain(),
appointmentsVM.serviceItemsFromApi.isEmpty
? Expanded(child: Center(child: LocaleKeys.noItemsToShow.toText(fontSize: 16, color: MyColors.lightTextColor)))
: ListView.separated(
separatorBuilder: (BuildContext context, int index) => const Divider(),
itemCount: appointmentsVM.serviceItemsFromApi.length,
itemBuilder: (BuildContext context, int index) {
ItemData itemData = appointmentsVM.serviceItemsFromApi[index];
return ServiceItemWithPriceCheckBox(
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.state == ViewState.busy
? const Center(child: CircularProgressIndicator())
: appointmentsVM.serviceItemsFromApi.isEmpty
? Expanded(child: Center(child: LocaleKeys.noAvailableItems.toText(fontSize: 16, color: MyColors.lightTextColor)))
: ListView.separated(
separatorBuilder: (BuildContext context, int index) => const Divider(),
itemCount: appointmentsVM.serviceItemsFromApi.length,
itemBuilder: (BuildContext context, int index) {
ItemData itemData = appointmentsVM.serviceItemsFromApi[index];
return ServiceItemWithPriceCheckBox(
description: itemData.description ?? LocaleKeys.someDescriptionSubServices.tr(),
title: itemData.name!,
isSelected: itemData.isUpdateOrSelected!,
onSelection: (bool value) {
appointmentsVM.onItemUpdateOrSelected(index, !itemData.isUpdateOrSelected!, itemData.id!);
},
priceWidget: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
itemData.price!.split(".").first.toText(fontSize: 30, isBold: true),
LocaleKeys.sar.tr().toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5),
],
),
);
},
priceWidget: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
itemData.price!.split(".").first.toText(fontSize: 30, isBold: true),
LocaleKeys.sar.tr().toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5),
],
),
);
},
).expand(),
).expand(),
Column(
children: [
const Divider(height: 1, thickness: 0.7),

@ -1,170 +1,170 @@
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';
import 'package:mc_common_app/widgets/common_widgets/branch_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);
@override
State<BookProviderAppView> createState() => _BookProviderAppViewState();
}
class _BookProviderAppViewState extends State<BookProviderAppView> {
bool isReview = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.appointment.tr(),
profileImageUrl: MyAssets.bnCar,
isRemoveBackButton: false,
isDrawerEnabled: false,
),
body: Container(
color: MyColors.backgroundColor,
width: double.infinity,
height: double.infinity,
child: Column(
children: [
Expanded(
child: ListView(
children: [
BranchDetailCard(
onCardTapped: () {},
providerImageUrl: MyAssets.bnCar,
providerLocation: "3km",
title: "Al Ahmed Maintenance",
providerRatings: 4.9,
),
12.height,
isReview ? const ReviewAppointmentSection() : const ServicesSelectionSection(),
10.height,
],
),
),
10.height,
Padding(
padding: const EdgeInsets.only(bottom: 10, left: 21, right: 21),
child: ShowFillButton(
title: LocaleKeys.bookAppointment.tr(),
maxWidth: double.infinity,
onPressed: () {
isReview = !isReview;
setState(() {});
},
),
),
],
),
),
);
}
}
class ServicesSelectionSection extends StatelessWidget {
const ServicesSelectionSection({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
List<DropValue> dropList = [
DropValue(0, "Maintenance", ""),
DropValue(1, "Car Wash", ""),
DropValue(2, "Monthly Checkup", ""),
DropValue(3, "Friendly Visit", ""),
DropValue(4, "Muftaa", ""),
];
return Container(
padding: const EdgeInsets.only(bottom: 10, left: 21, right: 21),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.selectServicesYouWant.tr().toText(fontSize: 18, isBold: true),
8.height,
DropdownField(
(DropValue value) {},
list: dropList,
hint: LocaleKeys.selectServiceType.tr(),
),
8.height,
DropdownField(
(DropValue value) {},
list: dropList,
hint: LocaleKeys.selectServiceType.tr(),
),
8.height,
DropdownField(
(DropValue value) {},
list: dropList,
hint: LocaleKeys.selectServiceType.tr(),
),
22.height,
LocaleKeys.selectDateAndTime.tr().toText(fontSize: 18, isBold: true),
8.height,
DropdownField(
(DropValue value) {},
list: dropList,
hint: LocaleKeys.selectServiceType.tr(),
),
22.height,
LocaleKeys.availableSlots.tr().toText(fontSize: 15, isBold: true),
8.height,
BuildTimeSlots(onPressed: (index) {}, timeSlots: []),
22.height,
LocaleKeys.totalAmount.tr().toText(fontSize: 18, isBold: true),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"3000".toText(fontSize: 20, isBold: true),
LocaleKeys.sar.tr().toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor),
],
),
10.height,
],
).toWhiteContainer(width: double.infinity, allPading: 12),
);
}
}
class ReviewAppointmentSection extends StatelessWidget {
const ReviewAppointmentSection({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(bottom: 10, left: 21, right: 21),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.reviewAppointment.tr().toText(fontSize: 18, isBold: true),
15.height,
LocaleKeys.services.tr().toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor),
LocaleKeys.carEngineCheck.tr().toText(fontSize: 18, isBold: true),
13.height,
LocaleKeys.dateAndTime.tr().toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor),
"2 Feb, 2023 at 09:00am".toText(fontSize: 18, isBold: true),
13.height,
LocaleKeys.totalAmount.tr().toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor),
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"3000".toText(fontSize: 20, isBold: true),
LocaleKeys.sar.tr().toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor),
],
),
100.height,
],
).toWhiteContainer(width: double.infinity, allPading: 12),
);
}
}
// 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';
// import 'package:mc_common_app/widgets/common_widgets/branch_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);
//
// @override
// State<BookProviderAppView> createState() => _BookProviderAppViewState();
// }
//
// class _BookProviderAppViewState extends State<BookProviderAppView> {
// bool isReview = false;
//
// @override
// Widget build(BuildContext context) {
// return Scaffold(
// appBar: CustomAppBar(
// title: LocaleKeys.appointment.tr(),
// profileImageUrl: MyAssets.bnCar,
// isRemoveBackButton: false,
// isDrawerEnabled: false,
// ),
// body: Container(
// color: MyColors.backgroundColor,
// width: double.infinity,
// height: double.infinity,
// child: Column(
// children: [
// Expanded(
// child: ListView(
// children: [
// BranchDetailCard(
// onCardTapped: () {},
// providerImageUrl: MyAssets.bnCar,
// providerLocation: "3km",
// title: "Al Ahmed Maintenance",
// providerRatings: 4.9,
// ),
// 12.height,
// isReview ? const ReviewAppointmentSection() : const ServicesSelectionSection(),
// 10.height,
// ],
// ),
// ),
// 10.height,
// Padding(
// padding: const EdgeInsets.only(bottom: 10, left: 21, right: 21),
// child: ShowFillButton(
// title: LocaleKeys.bookAppointment.tr(),
// maxWidth: double.infinity,
// onPressed: () {
// isReview = !isReview;
// setState(() {});
// },
// ),
// ),
// ],
// ),
// ),
// );
// }
// }
//
// class ServicesSelectionSection extends StatelessWidget {
// const ServicesSelectionSection({Key? key}) : super(key: key);
//
// @override
// Widget build(BuildContext context) {
// List<DropValue> dropList = [
// DropValue(0, "Maintenance", ""),
// DropValue(1, "Car Wash", ""),
// DropValue(2, "Monthly Checkup", ""),
// DropValue(3, "Friendly Visit", ""),
// DropValue(4, "Muftaa", ""),
// ];
// return Container(
// padding: const EdgeInsets.only(bottom: 10, left: 21, right: 21),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// LocaleKeys.selectServicesYouWant.tr().toText(fontSize: 18, isBold: true),
// 8.height,
// DropdownField(
// (DropValue value) {},
// list: dropList,
// hint: LocaleKeys.selectServiceType.tr(),
// ),
// 8.height,
// DropdownField(
// (DropValue value) {},
// list: dropList,
// hint: LocaleKeys.selectServiceType.tr(),
// ),
// 8.height,
// DropdownField(
// (DropValue value) {},
// list: dropList,
// hint: LocaleKeys.selectServiceType.tr(),
// ),
// 22.height,
// LocaleKeys.selectDateAndTime.tr().toText(fontSize: 18, isBold: true),
// 8.height,
// DropdownField(
// (DropValue value) {},
// list: dropList,
// hint: LocaleKeys.selectServiceType.tr(),
// ),
// 22.height,
// LocaleKeys.availableSlots.tr().toText(fontSize: 15, isBold: true),
// 8.height,
// BuildTimeSlots(onPressed: (index) {}, timeSlots: []),
// 22.height,
// LocaleKeys.totalAmount.tr().toText(fontSize: 18, isBold: true),
// Row(
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// "3000".toText(fontSize: 20, isBold: true),
// LocaleKeys.sar.tr().toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor),
// ],
// ),
// 10.height,
// ],
// ).toWhiteContainer(width: double.infinity, allPading: 12),
// );
// }
// }
//
// class ReviewAppointmentSection extends StatelessWidget {
// const ReviewAppointmentSection({Key? key}) : super(key: key);
//
// @override
// Widget build(BuildContext context) {
// return Container(
// padding: const EdgeInsets.only(bottom: 10, left: 21, right: 21),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// LocaleKeys.reviewAppointment.tr().toText(fontSize: 18, isBold: true),
// 15.height,
// LocaleKeys.services.tr().toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor),
// LocaleKeys.carEngineCheck.tr().toText(fontSize: 18, isBold: true),
// 13.height,
// LocaleKeys.dateAndTime.tr().toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor),
// "2 Feb, 2023 at 09:00am".toText(fontSize: 18, isBold: true),
// 13.height,
// LocaleKeys.totalAmount.tr().toText(fontSize: 14, isBold: true, color: MyColors.lightTextColor),
// Row(
// crossAxisAlignment: CrossAxisAlignment.end,
// children: [
// "3000".toText(fontSize: 20, isBold: true),
// LocaleKeys.sar.tr().toText(fontSize: 10, isBold: true, color: MyColors.lightTextColor),
// ],
// ),
// 100.height,
// ],
// ).toWhiteContainer(width: double.infinity, allPading: 12),
// );
// }
// }

@ -1,5 +1,8 @@
import 'dart:developer';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.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';
@ -9,15 +12,104 @@ 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';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/views/setting_options/widgets/custom_setting_options_tile.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:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
class ReviewAppointment extends StatelessWidget {
const ReviewAppointment({Key? key}) : super(key: key);
// buildProviderContactInfoBottomSheet(BuildContext context) {
// final appointmentsVM = context.read<AppointmentsVM>();
// log(": ${appointmentsVM.selectedBranchModel}");
// return showModalBottomSheet(
// context: context,
// isScrollControlled: true,
// enableDrag: true,
// builder: (BuildContext context) {
// return InfoBottomSheet(
// title: LocaleKeys.contactDetails.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
// description: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// if (requestVM.currentSelectedOffer!.mobileNo != null && requestVM.currentSelectedOffer!.mobileNo!.isNotEmpty) ...[
// CustomSettingOptionsTile(
// leadingWidget: const Icon(
// Icons.call,
// size: 20,
// color: MyColors.greyColor,
// ),
// titleText: LocaleKeys.phoneNumber.tr(),
// subTitle: " ${requestVM.currentSelectedOffer!.mobileNo ?? ""}",
// needBorderBelow: true,
// showTrailingArrow: false,
// subtitleTextColor: MyColors.greyColor,
// onTap: () {
// Utils.openNumberViaCaller(phoneNumber: requestVM.currentSelectedOffer!.mobileNo ?? "");
// },
// ),
// ],
// if (requestVM.currentSelectedOffer!.email != null && requestVM.currentSelectedOffer!.email!.isNotEmpty) ...[
// CustomSettingOptionsTile(
// leadingWidget: const Icon(
// Icons.email_outlined,
// size: 20,
// color: MyColors.greyColor,
// ),
// titleText: LocaleKeys.emailAddress.tr(),
// subTitle: " ${requestVM.currentSelectedOffer!.email ?? ""}",
// needBorderBelow: false,
// showTrailingArrow: false,
// subtitleTextColor: MyColors.greyColor,
// onTap: () {
// Utils.openEmailViaEmailApp(emailAddress: requestVM.currentSelectedOffer!.email ?? "");
// },
// ),
// ],
// 30.height,
// ],
// ),
// );
// },
// );
// }
Widget showItem(String title, String value) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"$title: ".toText(color: MyColors.lightTextColor, letterSpacing: -0.48),
3.width,
Flexible(child: value.toText(isBold: true, overflow: TextOverflow.ellipsis)),
],
);
}
Widget buildPersonalInformationCard({required BuildContext context}) {
return Padding(
padding: const EdgeInsets.only(
bottom: 0,
left: 21,
right: 21,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
(LocaleKeys.personalInformation.tr()).toText(fontSize: 16, isBold: true),
showItem(LocaleKeys.name.tr(), "${AppState().getUser.data!.userInfo!.firstName ?? ""} ${AppState().getUser.data!.userInfo!.lastName ?? ""}"),
showItem(LocaleKeys.phoneNumber.tr(), AppState().getUser.data!.userInfo!.mobileNo ?? ""),
showItem(LocaleKeys.email.tr(), AppState().getUser.data!.userInfo!.email ?? ""),
],
).toWhiteContainer(width: double.infinity, allPading: 12),
);
}
Widget buildBranchInfoCard({required BuildContext context}) {
AppointmentsVM appointmentsVM = context.read<AppointmentsVM>();
return Padding(
@ -28,8 +120,7 @@ class ReviewAppointment extends StatelessWidget {
),
child: Row(
children: [
Image.asset(
MyAssets.bnCar,
appointmentsVM.selectedBranchModel!.branchProfileImage.buildNetworkImage(
width: 80,
height: 60,
fit: BoxFit.cover,
@ -53,10 +144,38 @@ class ReviewAppointment extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flexible(
child: (appointmentsVM.selectedBranchModel!.branchDescription ?? "").toText(fontSize: 12),
child: (appointmentsVM.selectedBranchModel!.branchDescription ?? "").toText(fontSize: 12, color: MyColors.lightTextColor),
),
],
),
if ((appointmentsVM.selectedBranchModel!.latitude != null && appointmentsVM.selectedBranchModel!.latitude!.isNotEmpty) &&
(appointmentsVM.selectedBranchModel!.longitude != null && appointmentsVM.selectedBranchModel!.longitude!.isNotEmpty)) ...[
Row(
children: [
LocaleKeys.openMapLocation.tr().toText(
fontSize: 12,
isBold: true,
color: MyColors.primaryColor,
isUnderLine: true,
),
4.width,
Image.asset(
MyAssets.icRightUpPng,
height: 6,
width: 6,
color: MyColors.primaryColor,
),
],
).onPress(() async {
double latitude, longitude = 0.0;
latitude = double.parse(appointmentsVM.selectedBranchModel!.latitude!);
longitude = double.parse(appointmentsVM.selectedBranchModel!.longitude!);
await Utils.openLocationInMaps(latitude: latitude, longitude: longitude);
}),
] else ...[
const SizedBox(),
],
],
),
),
@ -80,7 +199,7 @@ class ReviewAppointment extends StatelessWidget {
),
),
],
).onPress(() {}).toWhiteContainer(width: double.infinity, allPading: 12));
).toWhiteContainer(width: double.infinity, allPading: 12));
}
Widget buildServicesInfoCard({required BuildContext context}) {
@ -135,13 +254,20 @@ class ReviewAppointment extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
("${itemData.name}: ${itemData.price} ${LocaleKeys.sar.tr()}").toText(fontSize: 13, isBold: true, color: MyColors.lightTextColor),
("${itemData.name}: ${itemData.price} ${LocaleKeys.sar.tr()}").toText(fontSize: 13, color: MyColors.lightTextColor),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
("${itemData.description}").toText(fontSize: 11, color: MyColors.lightTextColor),
],
),
],
);
}),
),
).paddingOnly(bottom: 10),
],
);
}),
@ -156,12 +282,12 @@ class ReviewAppointment extends StatelessWidget {
LocaleKeys.timeLocation.tr().toText(fontSize: 16, isBold: true),
3.height,
Row(children: [
"${LocaleKeys.dateAndTime.tr()}: ".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),
"${scheduleData.selectedCustomTimeDateSlotModel!.date!.date} at $selectedTimeSlot".toText(fontSize: 12),
]),
Row(children: [
("${LocaleKeys.location.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
(scheduleData.appointmentTypeEnum == AppointmentTypeEnum.home ? LocaleKeys.home.tr() : LocaleKeys.workshop.tr()).toText(fontSize: 12, isBold: true),
("${LocaleKeys.location.tr()}: ").toText(fontSize: 12, color: MyColors.lightTextColor),
(scheduleData.appointmentTypeEnum == AppointmentTypeEnum.home ? LocaleKeys.home.tr() : LocaleKeys.workshop.tr()).toText(fontSize: 12),
]),
],
),
@ -169,6 +295,7 @@ class ReviewAppointment extends StatelessWidget {
10.height,
const Divider(thickness: 0.7),
Builder(builder: (BuildContext context) {
//TODO: THIS SHOULD BE FINALIZED FROM API
double totalServicePrice = 0.0;
double totalKms = 15.3;
double rangePricePerKm = 5;
@ -181,7 +308,7 @@ class ReviewAppointment extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
LocaleKeys.serviceCharges.tr().toText(fontSize: 14, color: MyColors.lightTextColor, isBold: true),
LocaleKeys.serviceCharges.tr().toText(fontSize: 14, color: MyColors.lightTextColor),
"${scheduleData.amountTotal.toString()} ${LocaleKeys.sar.tr()}".toText(fontSize: 16, isBold: true),
],
),
@ -189,7 +316,7 @@ class ReviewAppointment extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
("${LocaleKeys.locationCharges.tr()} ($rangePricePerKm x $totalKms )").toText(fontSize: 14, color: MyColors.lightTextColor, isBold: true),
("${LocaleKeys.locationCharges.tr()} ($rangePricePerKm x $totalKms )").toText(fontSize: 14, color: MyColors.lightTextColor),
("${totalServicePrice.toString()} ${LocaleKeys.sar.tr()}").toText(fontSize: 16, isBold: true),
],
),
@ -289,6 +416,14 @@ class ReviewAppointment extends StatelessWidget {
isRemoveBackButton: false,
isDrawerEnabled: false,
onBackButtonTapped: () => Navigator.pop(context),
actions: [
IconButton(
onPressed: () {
// buildProviderContactInfoBottomSheet(context);
},
icon: const Icon(Icons.help_outline_outlined).paddingOnly(right: 21),
),
],
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -299,6 +434,8 @@ class ReviewAppointment extends StatelessWidget {
buildBranchInfoCard(context: context),
10.height,
buildServicesInfoCard(context: context),
10.height,
buildPersonalInformationCard(context: context),
],
).expand(),
buildNextButtonFooter(context: context),

@ -99,7 +99,7 @@ class AppointmentServicePickBottomSheet extends StatelessWidget {
if (appointmentsVM.currentServiceSelection != null && (appointmentsVM.currentServiceSelection!.isAllowAppointmentHome ?? false)) {
appointmentsVM.updateIsHomeTapped(true);
} else {
Utils.showToast("The Selected Service is not available at Home Location.");
Utils.showToast(LocaleKeys.serviceNotAvailableAtHomeLocation.tr());
}
},
),

@ -4,6 +4,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
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/extensions/string_extensions.dart';
@ -20,8 +21,10 @@ import 'package:mc_common_app/views/advertisement/components/picked_images_conta
import 'package:mc_common_app/views/chat/widgets/chat_bottom_sheets.dart';
import 'package:mc_common_app/views/chat/widgets/chat_message_widget.dart';
import 'package:mc_common_app/views/requests/request_bottomsheets.dart';
import 'package:mc_common_app/views/setting_options/widgets/custom_setting_options_tile.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: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';
@ -129,10 +132,9 @@ class _ChatViewState extends State<ChatView> {
),
);
}
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.chat.tr(),
),
appBar: CustomAppBar(title: LocaleKeys.chat.tr()),
body: Consumer2<ChatVM, RequestsVM>(builder: (BuildContext context, ChatVM chatVM, RequestsVM requestVM, Widget? child) {
List<ChatMessageModel> chatMessages = [];
if (chatTypeEnum == ChatTypeEnum.general) {

@ -1,3 +1,5 @@
import 'dart:developer';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
@ -21,6 +23,7 @@ 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;
import 'package:sizer/sizer.dart';
class ChatMessageCustomWidget extends StatefulWidget {
final ChatMessageModel chatMessageModel;
@ -407,10 +410,20 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
return widget.toCircle(borderRadius: 100);
}
Widget buildFreeTextDetailsInMessage() {
Widget buildFreeTextDetailsInMessage({required ChatMessageTypeEnum chatMessageTypeEnum}) {
log(": ${widget.chatMessageModel.isMyMessage}");
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (chatMessageTypeEnum == ChatMessageTypeEnum.offer && (widget.chatMessageModel.isMyMessage == true)) ...[
Row(
children: [
const Icon(Icons.remove_red_eye_outlined, size: 12, color: MyColors.lightTextColor),
4.width,
LocaleKeys.viewed.tr().toText(fontSize: 10, color: MyColors.lightTextColor, fontWeight: MyFonts.Medium),
],
),
],
Expanded(
child: Directionality(
textDirection: TextDirection.ltr,
@ -421,17 +434,12 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
),
),
),
],
);
}
Widget buildImageGridWidget({
required List<MessageImageModel> messagesImages,
double gridItemSize = 50.0,
double spacing = 8.0,
double borderWidth = 1,
Color borderColor = MyColors.textColor,
}) {
Widget buildImageGridWidget({required List<MessageImageModel> messagesImages, double gridItemSize = 50.0, double spacing = 8.0, double borderWidth = 1, Color borderColor = MyColors.textColor}) {
int imageCount = messagesImages.length;
if (imageCount == 1) {
return Container(
@ -529,7 +537,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
}
switch (chatMessageTypeEnum) {
case ChatMessageTypeEnum.freeText:
messageTypeWidget = Column(children: [buildFreeTextDetailsInMessage(), 10.height]);
messageTypeWidget = Column(children: [buildFreeTextDetailsInMessage(chatMessageTypeEnum: chatMessageTypeEnum), 10.height]);
break;
case ChatMessageTypeEnum.image:
messageTypeWidget = buildImageGridWidget(messagesImages: widget.chatMessageModel.messageImages ?? []);
@ -540,7 +548,7 @@ class _ChatMessageCustomWidgetState extends State<ChatMessageCustomWidget> {
case ChatMessageTypeEnum.offer:
messageTypeWidget = Column(
children: [
buildFreeTextDetailsInMessage(),
buildFreeTextDetailsInMessage(chatMessageTypeEnum: chatMessageTypeEnum),
10.height,
buildOfferDetailsInChatMessage(requestStatusEnum: widget.requestStatusEnum!, chatMessageModel: widget.chatMessageModel, context: context),
],

@ -76,7 +76,7 @@ class MyRequestsFragment extends StatelessWidget {
return Consumer(builder: (BuildContext context, RequestsVM requestsVM, Widget? child) {
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.myRequests.tr(),
title: LocaleKeys.manageRequests.tr(),
isRemoveBackButton: true,
actions: [
Padding(

@ -1,3 +1,4 @@
import 'dart:developer';
import 'dart:ui';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
@ -7,7 +8,10 @@ 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/subscriptions_models/subscription_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/date_helper.dart';
import 'package:mc_common_app/utils/enums.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/views/setting_options/widgets/custom_setting_options_tile.dart';
@ -34,10 +38,26 @@ class _ProfileScreenState extends State<ProfileScreen> {
@override
Widget build(BuildContext context) {
Subscription? mySubscription;
return Scaffold(
extendBody: true,
backgroundColor: const Color(0xffefefef),
body: Consumer<UserVM>(builder: (_, model, __) {
String startDate = "";
String endDate = "";
String freeTrialName = "";
if (AppState().currentAppType == AppType.provider && AppState().getproviderSubscription.isNotEmpty) {
mySubscription = AppState().getproviderSubscription.first;
log("mySubscription!.dateStart.toString(): ${mySubscription!.dateStart}");
log("mySubscription!.dateEnd.toString(): ${mySubscription!.dateEnd}");
if (mySubscription!.id == 1) {
freeTrialName = mySubscription!.name ?? "";
} else {
startDate = (mySubscription!.dateStart != null && mySubscription!.dateStart!.isNotEmpty) ? DateHelper.formatAsDayMonthYear(DateHelper.parseStringToDate(DateHelper.formatDateT(mySubscription!.dateStart!))) : "";
endDate = (mySubscription!.dateEnd != null && mySubscription!.dateEnd!.isNotEmpty) ? DateHelper.formatAsDayMonthYear(DateHelper.parseStringToDate(DateHelper.formatDateT(mySubscription!.dateEnd!))) : "";
}
}
return Stack(
children: [
Column(
@ -84,6 +104,15 @@ class _ProfileScreenState extends State<ProfileScreen> {
"${AppState().getUser.data!.userInfo!.firstName} ${AppState().getUser.data!.userInfo!.lastName ?? ""}".toText(fontSize: 20).paddingOnly(left: 25),
Column(
children: [
if (AppState().currentAppType == AppType.provider && mySubscription != null) ...[
CustomProfileOptionsTile(
titleText: LocaleKeys.mySubscription.tr(),
subtitleText: freeTrialName.isNotEmpty ? freeTrialName : "${startDate.isNotEmpty ? "${LocaleKeys.startDate.tr()}: $startDate" : ""} ${endDate.isNotEmpty ? "${LocaleKeys.expiresOn.tr()}: $endDate" : ""}",
needBorderBelow: true,
needEditButton: false,
onTap: () {},
),
],
CustomProfileOptionsTile(
titleText: LocaleKeys.country.tr(),
subtitleText: "Saudi Arabia",
@ -163,7 +192,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
child: Container(
height: 40,
width: 40,
padding: EdgeInsets.all(8),
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(color: MyColors.white, shape: BoxShape.circle, border: Border.all(color: MyColors.darkTextColor, width: 0.1)),
child: MyAssets.icEdit.buildSvg(),
).onPress(

@ -27,6 +27,10 @@ class CreateRequestPage extends StatelessWidget {
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.createRequest.tr(),
onBackButtonTapped: () {
context.read<RequestsVM>().resetRequestCreationForm();
pop(context);
},
),
body: Consumer<RequestsVM>(builder: (context, requestsVM, widget) {
return Column(
@ -133,8 +137,7 @@ class CreateRequestPage extends StatelessWidget {
return DropdownField(
(DropValue value) => requestsVM.updateSelectionVehicleConditionId(SelectionModel(selectedId: value.id, selectedOption: value.value)),
list: vehicleOwnerDrop,
dropdownValue:
requestsVM.vehicleConditionId.selectedId != -1 ? DropValue(requestsVM.vehicleConditionId.selectedId, requestsVM.vehicleConditionId.selectedOption, "") : null,
dropdownValue: requestsVM.vehicleConditionId.selectedId != -1 ? DropValue(requestsVM.vehicleConditionId.selectedId, requestsVM.vehicleConditionId.selectedOption, "") : null,
hint: LocaleKeys.condition.tr(),
errorValue: requestsVM.vehicleConditionId.errorValue,
);

@ -39,7 +39,7 @@ class OfferListPage extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Utils.statusContainerChip(
text: "Offer ${Utils.getNameByRequestOfferStatusEnum(offersModel.requestOfferStatusEnum!)}",
text: Utils.getNameByRequestOfferStatusEnum(offersModel.requestOfferStatusEnum!),
chipColor: Utils.getChipColorByRequestOfferStatusEnum(offersModel.requestOfferStatusEnum!),
),
Row(
@ -54,7 +54,7 @@ class OfferListPage extends StatelessWidget {
fontSize: 10,
),
).toContainer(
backgroundColor: MyColors.redColor,
backgroundColor: MyColors.cancelledColor,
borderRadius: 100,
paddingAll: 1,
width: 22,
@ -85,6 +85,7 @@ class OfferListPage extends StatelessWidget {
],
).onPress(() async {
context.read<RequestsVM>().currentSelectedOffer = offersModel;
ChatViewArgumentsForRequest chatViewArgumentsForRequest = ChatViewArgumentsForRequest(
chatTypeEnum: ChatTypeEnum.requestOffer,
receiverId: "${offersModel.providerUserId}",
@ -106,9 +107,7 @@ class OfferListPage extends StatelessWidget {
requestId: offerListPageArguments.requestId ?? 0,
providerOfferIndex: index,
)
.whenComplete(
() => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments),
);
.whenComplete(() => navigateWithName(context, AppRoutes.chatView, arguments: chatViewArguments));
}).toContainer(isShadowEnabled: true);
},
separatorBuilder: (context, index) => 16.height,

@ -1,4 +1,6 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.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/extensions/string_extensions.dart';
@ -9,9 +11,12 @@ import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_creation_steps_containers.dart';
import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/checkbox_with_title_desc.dart';
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';
@ -81,6 +86,50 @@ Future buildSendOfferBottomSheet({required BuildContext context, required Reques
hint: LocaleKeys.description.tr(),
onChanged: (v) => requestsVM.updateOfferDescription(v),
),
12.height,
if (requestDetail.requestType == RequestsTypeEnum.serviceRequest.getIdFromRequestTypeStatusEnum()) ...[
LocaleKeys.deliveryAvailable.tr().toText(fontSize: 16),
8.height,
Container(
width: 50,
height: 30,
decoration: BoxDecoration(
color: requestsVM.isDeliveryAvailableStatus ? MyColors.darkPrimaryColor : MyColors.white,
borderRadius: BorderRadius.circular(25.0),
border: Border.all(color: MyColors.black, width: 1),
),
child: Transform.scale(
scale: 0.8,
child: CupertinoSwitch(
activeColor: MyColors.darkPrimaryColor,
trackColor: MyColors.white,
thumbColor: MyColors.grey98Color,
value: requestsVM.isDeliveryAvailableStatus,
onChanged: (value) {
requestsVM.updateIsDeliveryAvailableStatus(value);
},
),
),
),
],
12.height,
if (requestsVM.pickedVehicleImages.isEmpty) ...[
DottedRectContainer(
onTap: () => context.read<RequestsVM>().pickMultipleImages(),
text: LocaleKeys.attachImage.tr(),
icon: MyAssets.attachmentIcon.buildSvg(),
),
],
if (requestsVM.pickedVehicleImages.isNotEmpty) ...[
16.height,
PickedFilesContainer(
pickedFiles: requestsVM.pickedVehicleImages,
onCrossPressedPrimary: requestsVM.removeImageFromList,
onAddFilePressed: () {
context.read<RequestsVM>().pickMultipleImages();
},
),
],
],
),
25.height,

@ -137,7 +137,7 @@ class RequestDetailPage extends StatelessWidget {
children: [
ImagesCorouselWidget(imagesList: requestDetailPageArguments.requestModel.requestImages ?? []),
24.height,
buildRequestContainer(context),
buildRequestDetailsContainer(context),
],
).toWhiteContainer(
width: double.infinity,
@ -169,7 +169,7 @@ class RequestDetailPage extends StatelessWidget {
);
}
Widget buildRequestContainer(BuildContext context) {
Widget buildRequestDetailsContainer(BuildContext context) {
final requestDetail = requestDetailPageArguments.requestModel;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
@ -184,8 +184,9 @@ class RequestDetailPage extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start,
children: [
requestDetail.vehicleTypeName.toText(fontSize: 16, letterSpacing: -0.64),
showItem("${LocaleKeys.manufacturer.tr()}: ", requestDetail.brand),
showItem("${LocaleKeys.model.tr()}: ", "${requestDetail.year}"),
showItem("${LocaleKeys.brand.tr()}: ", requestDetail.brand),
showItem("${LocaleKeys.model.tr()}: ", requestDetail.model),
showItem("${LocaleKeys.year.tr()}: ", "${requestDetail.year}"),
],
),
),
@ -205,7 +206,9 @@ class RequestDetailPage extends StatelessWidget {
),
],
),
showItem("${LocaleKeys.customerName.tr()}: ", requestDetail.customerName),
if (requestDetail.customerName.isNotEmpty) ...[
showItem("${LocaleKeys.customerName.tr()}: ", requestDetail.customerName),
],
showItem("${LocaleKeys.description.tr()}: ", requestDetail.description),
16.height,
// showItem("${LocaleKeys.priceRange.tr()}:", ""),

@ -7,6 +7,7 @@ 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/user_models/user.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/date_helper.dart';
import 'package:mc_common_app/utils/dialogs_and_bottomsheets.dart';
import 'package:mc_common_app/utils/enums.dart';
@ -16,6 +17,7 @@ import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/views/advertisement/ad_creation_steps/ad_review_containers.dart';
import 'package:mc_common_app/views/location_views/pick_location_page.dart';
import 'package:mc_common_app/views/setting_options/widgets/custom_setting_options_tile.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:mc_common_app/widgets/common_widgets/info_bottom_sheet.dart';
@ -255,6 +257,61 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
);
}
buildProviderContactInfoBottomSheet(BuildContext context) {
final requestVM = context.read<RequestsVM>();
return showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
return InfoBottomSheet(
title: LocaleKeys.contactDetails.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (requestVM.currentSelectedOffer!.mobileNo != null && requestVM.currentSelectedOffer!.mobileNo!.isNotEmpty) ...[
CustomSettingOptionsTile(
leadingWidget: const Icon(
Icons.call,
size: 20,
color: MyColors.greyColor,
),
titleText: LocaleKeys.phoneNumber.tr(),
subTitle: " ${requestVM.currentSelectedOffer!.mobileNo ?? ""}",
needBorderBelow: true,
showTrailingArrow: false,
subtitleTextColor: MyColors.greyColor,
onTap: () {
Utils.openNumberViaCaller(phoneNumber: requestVM.currentSelectedOffer!.mobileNo ?? "");
},
),
],
if (requestVM.currentSelectedOffer!.email != null && requestVM.currentSelectedOffer!.email!.isNotEmpty) ...[
CustomSettingOptionsTile(
leadingWidget: const Icon(
Icons.email_outlined,
size: 20,
color: MyColors.greyColor,
),
titleText: LocaleKeys.emailAddress.tr(),
subTitle: " ${requestVM.currentSelectedOffer!.email ?? ""}",
needBorderBelow: false,
showTrailingArrow: false,
subtitleTextColor: MyColors.greyColor,
onTap: () {
Utils.openEmailViaEmailApp(emailAddress: requestVM.currentSelectedOffer!.email ?? "");
},
),
],
30.height,
],
),
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -265,7 +322,7 @@ class _ReviewRequestOfferState extends State<ReviewRequestOffer> {
onBackButtonTapped: () => Navigator.pop(context),
actions: [
IconButton(
onPressed: () => Utils.showHelpBottomSheet(context),
onPressed: () => buildProviderContactInfoBottomSheet(context),
icon: const Icon(Icons.help_outline_outlined).paddingOnly(right: 21),
),
],

@ -35,10 +35,10 @@ 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.toLowerCase() == "InProgress".toLowerCase() ? "In Progress" : request.requestStatusName, chipColor: Utils.getChipColorByRequestStatus(request.requestStatus)),
6.height,
"${request.brand} ${request.model} | ${request.id}".toText(fontSize: 16, letterSpacing: -0.64),
showItem("${LocaleKeys.model.tr()}:", "${request.year}"),
showItem("${LocaleKeys.year.tr()}:", "${request.year}"),
if (request.customerName.isNotEmpty) ...[
showItem("${LocaleKeys.customerName.tr()}:", request.customerName),
],

@ -57,7 +57,7 @@ class SettingOptionsHelp extends StatelessWidget {
),
titleText: LocaleKeys.termPrivacy.tr(),
needBorderBelow: true,
onTap: () {},
onTap: () => navigateWithName(context, AppRoutes.settingOptionsTermsAndConditions),
),
CustomSettingOptionsTile(
leadingWidget: const Icon(

@ -2,15 +2,15 @@ import 'dart:async';
import 'package:flutter/cupertino.dart';
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/models/chat_models/chat_message_model.dart';
import 'package:mc_common_app/models/setting_utils_models/app_info_model.dart';
import 'package:mc_common_app/models/setting_utils_models/contact_infos_model.dart';
import 'package:mc_common_app/models/setting_utils_models/faqs_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/setting_options_view_model.dart';
import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
@ -76,7 +76,7 @@ class _SettingOptionsAppInfoState extends State<SettingOptionsAppInfo> {
16.height,
Expanded(
child: RefreshIndicator(
onRefresh: () async => await settingsOptionsVM.getAllFaqs(),
onRefresh: () async => await settingsOptionsVM.getAppInfoList(),
child: (settingsOptionsVM.state == ViewState.busy)
? const Center(child: CircularProgressIndicator())
: settingsOptionsVM.appInfoList.isEmpty
@ -95,12 +95,22 @@ class _SettingOptionsAppInfoState extends State<SettingOptionsAppInfo> {
(appInfoModel.header ?? "").toString().toText(fontSize: 16),
5.height,
(appInfoModel.content ?? "").toString().toText(fontSize: 14, color: MyColors.lightTextColor),
if (appInfoModel.appInfoImages != null && appInfoModel.appInfoImages!.isNotEmpty) ...[
if (appInfoModel.images != null && appInfoModel.images!.isNotEmpty) ...[
PickedFilesContainer(
pickedFiles: appInfoModel.appInfoImages ?? [],
pickedFiles: appInfoModel.images ?? [],
isReview: true,
onAddFilePressed: () {},
),
).onPress(() {
List<MessageImageModel> images = [];
for (var image in appInfoModel.images!) {
images.add(MessageImageModel(
id: image.id,
isFromNetwork: true,
imageUrl: image.filePath,
));
}
navigateWithName(context, AppRoutes.mediaViewerScreen, arguments: images);
}),
]
],
).toContainer(isShadowEnabled: true);

@ -2,12 +2,16 @@ import 'dart:async';
import 'package:flutter/cupertino.dart';
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/models/chat_models/chat_message_model.dart';
import 'package:mc_common_app/models/setting_utils_models/contact_infos_model.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';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/setting_options_view_model.dart';
import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
@ -92,7 +96,14 @@ class _SettingOptionsContactUsState extends State<SettingOptionsContactUs> {
children: [
contactInfoModel.companyName.toString().toText(fontSize: 16),
5.height,
LocaleKeys.openMapLocation.tr().toText(isUnderLine: true, color: MyColors.darkPrimaryColor, fontSize: 10).onPress(() {}),
if (contactInfoModel.latitude != null && contactInfoModel.latitude!.isNotEmpty && contactInfoModel.longitude != null && contactInfoModel.longitude!.isNotEmpty) ...[
LocaleKeys.openMapLocation.tr().toText(isUnderLine: true, color: MyColors.darkPrimaryColor, fontSize: 10).onPress(() async {
double latitude, longitude = 0.0;
latitude = double.parse(contactInfoModel.latitude!);
longitude = double.parse(contactInfoModel.longitude!);
await Utils.openLocationInMaps(latitude: latitude, longitude: longitude);
}),
],
showData("${LocaleKeys.phoneNumber.tr()}:", "${contactInfoModel.phoneNo}"),
showData("${LocaleKeys.email.tr()}:", "${contactInfoModel.email}"),
if (contactInfoModel.address != null && contactInfoModel.address!.isNotEmpty) ...[
@ -104,7 +115,17 @@ class _SettingOptionsContactUsState extends State<SettingOptionsContactUs> {
pickedFiles: contactInfoModel.contactInfoImages ?? [],
isReview: true,
onAddFilePressed: () {},
),
).onPress(() {
List<MessageImageModel> images = [];
for (var image in contactInfoModel.contactInfoImages!) {
images.add(MessageImageModel(
id: image.id,
isFromNetwork: true,
imageUrl: image.filePath,
));
}
navigateWithName(context, AppRoutes.mediaViewerScreen, arguments: images);
}),
]
],
).toContainer(isShadowEnabled: true);

@ -1,15 +1,20 @@
import 'package:flutter/material.dart';
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/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/navigator.dart';
import 'package:mc_common_app/view_models/setting_options_view_model.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/common_widgets/info_bottom_sheet.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:provider/provider.dart';
class SettingOptionsInviteFriends extends StatelessWidget {
const SettingOptionsInviteFriends({super.key});
@ -21,22 +26,24 @@ class SettingOptionsInviteFriends extends StatelessWidget {
enableDrag: true,
builder: (BuildContext context) {
return InfoBottomSheet(
description: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
20.height,
CustomSettingOptionsTile(
leadingWidget: MyAssets.whatsAppIcon.buildSvg(
height: 20,
width: 20,
color: MyColors.greyColor,
),
titleText: LocaleKeys.inviteFriendsByWhatsApp.tr(),
needBorderBelow: true,
showTrailingArrow: false,
onTap: () {},
title: LocaleKeys.inviteFriends.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
description: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CustomSettingOptionsTile(
leadingWidget: MyAssets.whatsAppIcon.buildSvg(
height: 20,
width: 20,
color: MyColors.greyColor,
),
CustomSettingOptionsTile(
titleText: LocaleKeys.inviteFriendsByWhatsApp.tr(),
needBorderBelow: true,
showTrailingArrow: false,
onTap: () async {
await context.read<SettingOptionsVM>().appInvitationCreate(context: context, channelId: 1);
},
),
CustomSettingOptionsTile(
leadingWidget: const Icon(
Icons.sms_outlined,
size: 20,
@ -45,23 +52,26 @@ class SettingOptionsInviteFriends extends StatelessWidget {
titleText: LocaleKeys.inviteFriendsBySMS.tr(),
needBorderBelow: true,
showTrailingArrow: false,
onTap: () {},
),
CustomSettingOptionsTile(
leadingWidget: const Icon(
Icons.email_outlined,
size: 20,
color: MyColors.greyColor,
),
titleText: LocaleKeys.inviteFriendsByEmail.tr(),
needBorderBelow: false,
showTrailingArrow: false,
onTap: () {},
onTap: () async {
await context.read<SettingOptionsVM>().appInvitationCreate(context: context, channelId: 2);
}),
CustomSettingOptionsTile(
leadingWidget: const Icon(
Icons.email_outlined,
size: 20,
color: MyColors.greyColor,
),
30.height,
],
),
title: const SizedBox());
titleText: LocaleKeys.inviteFriendsByEmail.tr(),
needBorderBelow: false,
showTrailingArrow: false,
onTap: () async {
await context.read<SettingOptionsVM>().appInvitationCreate(context: context, channelId: 3);
},
),
30.height,
],
),
);
},
);
}
@ -82,14 +92,16 @@ class SettingOptionsInviteFriends extends StatelessWidget {
children: [
Column(
children: [
CustomSettingOptionsTile(
leadingWidget: const Icon(Icons.group, size: 20),
titleText: LocaleKeys.inviteFriends.tr(),
needBorderBelow: true,
onTap: () {
return buildInviteFriendsBottomSheet(context);
},
),
if (AppState().currentAppType == AppType.customer) ...[
CustomSettingOptionsTile(
leadingWidget: const Icon(Icons.group, size: 20),
titleText: LocaleKeys.inviteFriends.tr(),
needBorderBelow: true,
onTap: () {
return buildInviteFriendsBottomSheet(context);
},
),
],
CustomSettingOptionsTile(
leadingWidget: const Icon(Icons.question_mark_outlined, size: 20),
titleText: LocaleKeys.help.tr(),

@ -5,9 +5,11 @@ 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/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/main.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/dialogs_and_bottomsheets.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/user_view_model.dart';
@ -25,6 +27,38 @@ class SettingOptionsMore extends StatefulWidget {
}
class _SettingOptionsMoreState extends State<SettingOptionsMore> {
void logoutConfirmationSheet(BuildContext context) {
return actionConfirmationBottomSheet(
context: context,
title: LocaleKeys.logoutConfirmation.tr().toText(fontSize: 28, isBold: true, letterSpacing: -1.44),
subtitle: LocaleKeys.logoutConfirmationMessage.tr(),
actionButtonYes: Expanded(
child: ShowFillButton(
maxHeight: 55,
title: LocaleKeys.yes.tr(),
fontSize: 15,
onPressed: () {
Navigator.pop(context);
context.read<UserVM>().logout(context);
},
),
),
actionButtonNo: Expanded(
child: ShowFillButton(
maxHeight: 55,
isFilled: false,
borderColor: MyColors.darkPrimaryColor,
title: LocaleKeys.no.tr(),
txtColor: MyColors.darkPrimaryColor,
fontSize: 15,
onPressed: () {
Navigator.pop(context);
},
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -109,10 +143,7 @@ class _SettingOptionsMoreState extends State<SettingOptionsMore> {
leadingWidget: SizedBox(
width: 16,
height: 16,
child: SvgPicture.asset(
MyAssets.icGroupStar,
// color: MyColors.primaryColor,
),
child: SvgPicture.asset(MyAssets.icGroupStar),
),
titleText: LocaleKeys.subscriptions.tr(),
subTitle: null,
@ -196,7 +227,7 @@ class _SettingOptionsMoreState extends State<SettingOptionsMore> {
maxHeight: 55,
title: LocaleKeys.logOut.tr(),
onPressed: () {
context.read<UserVM>().logout(context);
logoutConfirmationSheet(context);
},
),
),
@ -207,5 +238,3 @@ class _SettingOptionsMoreState extends State<SettingOptionsMore> {
);
}
}

@ -0,0 +1,127 @@
import 'dart:async';
import 'package:flutter/cupertino.dart';
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/models/chat_models/chat_message_model.dart';
import 'package:mc_common_app/models/setting_utils_models/app_info_model.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';
import 'package:mc_common_app/view_models/setting_options_view_model.dart';
import 'package:mc_common_app/views/advertisement/components/picked_images_container_widget.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';
import 'package:provider/provider.dart';
class SettingOptionsTermsAndConditions extends StatefulWidget {
const SettingOptionsTermsAndConditions({super.key});
@override
State<SettingOptionsTermsAndConditions> createState() => _SettingOptionsTermsAndConditionsState();
}
class _SettingOptionsTermsAndConditionsState extends State<SettingOptionsTermsAndConditions> {
late SettingOptionsVM settingsOptionsVM;
@override
void initState() {
settingsOptionsVM = context.read<SettingOptionsVM>();
scheduleMicrotask(() async {
await settingsOptionsVM.getTermsAndConditions();
});
super.initState();
}
Widget showData(String title, String value) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
title.toText(
fontSize: 13,
color: MyColors.darkTextColor,
),
if (title.isNotEmpty) 5.width,
Flexible(
child: value.toText(
fontSize: 13,
color: MyColors.lightTextColor,
),
)
],
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.termPrivacy.tr(),
isRemoveBackButton: false,
isDrawerEnabled: false,
onBackButtonTapped: () => Navigator.pop(context),
),
body: Consumer(
builder: (BuildContext context, SettingOptionsVM settingsOptionsVM, Widget? child) {
return Container(
color: MyColors.backgroundColor,
width: double.infinity,
height: double.infinity,
child: Column(
children: [
16.height,
Expanded(
child: RefreshIndicator(
onRefresh: () async => await settingsOptionsVM.getTermsAndConditions(),
child: (settingsOptionsVM.state == ViewState.busy)
? const Center(child: CircularProgressIndicator())
: settingsOptionsVM.termsAndConditionsList.isEmpty
? Padding(
padding: const EdgeInsets.all(21),
child: Center(child: LocaleKeys.somethingWrong.tr().toText(textAlign: TextAlign.center, fontSize: 16, color: MyColors.lightTextColor)),
)
: ListView.separated(
itemCount: settingsOptionsVM.termsAndConditionsList.length,
padding: const EdgeInsets.all(16),
itemBuilder: (context, index) {
AppInfoModel appInfoModel = settingsOptionsVM.termsAndConditionsList[index];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
(appInfoModel.header ?? "").toString().toText(fontSize: 16),
5.height,
(appInfoModel.content ?? "").toString().toText(fontSize: 14, color: MyColors.lightTextColor),
if (appInfoModel.images != null && appInfoModel.images!.isNotEmpty) ...[
PickedFilesContainer(
pickedFiles: appInfoModel.images ?? [],
isReview: true,
onAddFilePressed: () {},
).onPress(() {
List<MessageImageModel> images = [];
for (var image in appInfoModel.images!) {
images.add(MessageImageModel(
id: image.id,
isFromNetwork: true,
imageUrl: image.filePath,
));
}
navigateWithName(context, AppRoutes.mediaViewerScreen, arguments: images);
}),
]
],
).toContainer(isShadowEnabled: true);
},
separatorBuilder: (context, index) => 16.height,
),
)),
],
),
);
},
));
}
}

@ -15,6 +15,7 @@ class CustomSettingOptionsTile extends StatelessWidget {
final bool showTrailingArrow;
final Function() onTap;
final String? subTitle;
final Color subtitleTextColor;
const CustomSettingOptionsTile({
super.key,
@ -25,6 +26,7 @@ class CustomSettingOptionsTile extends StatelessWidget {
this.isForLanguage = false,
this.showTrailingArrow = true,
this.subTitle,
this.subtitleTextColor = MyColors.primaryColor,
});
@override
@ -48,7 +50,7 @@ class CustomSettingOptionsTile extends StatelessWidget {
Row(
children: [
28.width,
subTitle!.toText(fontSize: 14, color: MyColors.primaryColor),
subTitle!.toText(fontSize: 14, color: subtitleTextColor),
],
),
],

@ -1,12 +1,15 @@
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/theme/colors.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/user_models/register_user.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_fill_button.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
@ -119,13 +122,12 @@ class _CompleteProfilePageState extends State<CompleteProfilePage> {
Consumer(builder: (BuildContext context, UserVM userVM, Widget? child) {
return Checkbox(
value: userVM.completeProfilePageCheckbox,
activeColor: Colors.blue,
activeColor: MyColors.darkPrimaryColor,
onChanged: (value) {
userVM.updateCompleteProfilePageCheckbox(value!);
},
);
}),
Expanded(
child: Text.rich(
TextSpan(
@ -144,7 +146,9 @@ class _CompleteProfilePageState extends State<CompleteProfilePage> {
))
],
),
),
).onPress(() {
navigateWithName(context, AppRoutes.settingOptionsTermsAndConditions);
}),
)
// Column(
// children: [
@ -162,29 +166,35 @@ class _CompleteProfilePageState extends State<CompleteProfilePage> {
],
),
16.height,
ShowFillButton(
title: LocaleKeys.save.tr(),
maxWidth: double.infinity,
onPressed: () {
bool validateStatus = userVM.dataValidation(
password: password,
firstName: firstName,
lastName: lastName,
email: email,
);
if (validateStatus) {
userVM.performCompleteProfile(
context,
Consumer(builder: (BuildContext context, UserVM userVM, Widget? child) {
return ShowFillButton(
title: LocaleKeys.save.tr(),
maxWidth: double.infinity,
isDisabled: !userVM.completeProfilePageCheckbox,
onPressed: () {
if (!userVM.completeProfilePageCheckbox) {
return;
}
bool validateStatus = userVM.dataValidation(
password: password,
confirmPassword: confirmPassword!,
firstName: firstName!,
lastName: lastName!,
email: email!,
userId: widget.user.data!.userId ?? "",
isNeedToPassToken: widget.user.data!.isNeedToPassToken,
firstName: firstName,
lastName: lastName,
email: email,
);
}
}),
if (validateStatus) {
userVM.performCompleteProfile(
context,
password: password,
confirmPassword: confirmPassword!,
firstName: firstName!,
lastName: lastName!,
email: email!,
userId: widget.user.data!.userId ?? "",
isNeedToPassToken: widget.user.data!.isNeedToPassToken,
);
}
});
}),
16.height,
],
),

@ -40,7 +40,7 @@ class CustomBottomNavbar extends StatelessWidget {
color: MyColors.lightIconColor,
).paddingAll(5),
activeIcon: SvgPicture.asset(MyAssets.homeIcon, color: MyColors.darkIconColor).paddingAll(5),
label: LocaleKeys.home.tr(),
label: LocaleKeys.explore.tr(),
),
BottomNavigationBarItem(
icon: SvgPicture.asset(MyAssets.announcementIcon).paddingAll(5),

@ -17,6 +17,7 @@ class ProviderDetailCard extends StatelessWidget {
final String description;
final List<BranchDetailModel> branches;
final Function() onCardTapped;
final bool isFromFavoriteList;
const ProviderDetailCard({
Key? key,
@ -27,6 +28,7 @@ class ProviderDetailCard extends StatelessWidget {
required this.description,
required this.startedSince,
required this.onCardTapped,
this.isFromFavoriteList = false,
}) : super(key: key);
@override
@ -57,21 +59,23 @@ class ProviderDetailCard extends StatelessWidget {
title.toText(fontSize: 16, isBold: true),
Row(
children: [
("Total Branches:").toText(color: MyColors.lightTextColor, fontSize: 12),
("${LocaleKeys.totalBranches.tr()}:").toText(color: MyColors.lightTextColor, fontSize: 12),
4.width,
totalBranches.toText(fontSize: 12, isBold: true),
],
),
if (description.isNotEmpty) ...[
Row(
children: [
("${LocaleKeys.description.tr()}:").toText(color: MyColors.lightTextColor, fontSize: 12),
4.width,
description.toText(fontSize: 12, isBold: true),
],
),
],
Row(
children: [
("${LocaleKeys.description.tr()}:").toText(color: MyColors.lightTextColor, fontSize: 12),
4.width,
description.toText(fontSize: 12, isBold: true),
],
),
Row(
children: [
("Since:").toText(color: MyColors.lightTextColor, fontSize: 12),
(isFromFavoriteList ? LocaleKeys.addToFavoritesOn.tr() : LocaleKeys.memberSince.tr()).toText(color: MyColors.lightTextColor, fontSize: 12),
4.width,
startedSince.toText(fontSize: 12, isBold: true),
],

@ -202,7 +202,7 @@ class TxtField extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
errorValue.toText(fontSize: 14, color: Colors.red),
errorValue.toText(fontSize: 12, color: Colors.red),
],
).paddingOnly(right: 10),
],

Loading…
Cancel
Save