Merge branch 'aamir_dev' into faiz_development_common

# Conflicts:
#	assets/langs/ar-SA.json
#	assets/langs/en-US.json
#	lib/generated/codegen_loader.g.dart
#	lib/generated/locale_keys.g.dart
#	lib/view_models/appointments_view_model.dart
master_new_changes
Faiz Hashmi 2 years ago
commit a6d75fdcc3

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -76,7 +76,7 @@
"userRoleOrTitle": "عنوان المستخدم",
"codeSentToEmail": "تم ارسال الرمز للايميل",
"number": "موبايل",
"english": "English",
"english": "عربي",
"title": "مرحبًا",
"msg": "Hello {} in the {} world ",
"msg_named": "{} are written in the {lang} language",
@ -491,7 +491,7 @@
"submitAd": "إرسال الإعلان",
"selectAdType": "اختر نوع الإعلان",
"validUntilSubscriptionExpiration": "صالح حتى انتهاء الاشتراك",
"adsRemaining": "الإعلانات المتبقية",
"adsRemainingVar": "الإعلانات المتبقية",
"youLeftAdsGivenSubscription": "لقد بقي لديك 05 من 50 إعلانًا في الاشتراك.",
"updateSubscription": "تحديث الاشتراك",
"workInProgress": "العمل جارٍ",
@ -561,11 +561,22 @@
"inviteFriends": "دعوة الأصدقاء",
"more": "المزيد",
"language": "اللغة",
"mySubscriptions": "اشتراكاتي",
"mySubscription": "اشتراكاتي",
"subscriptions": "الاشتراكات",
"defineLicenses": "تحديد التراخيص",
"logOut": "تسجيل الخروج",
"customer": "العميل",
"amountVAR": "كمية",
"accept": "قبول",
"requestAlreadyInProgress": "هذا الطلب قيد التقدم بالفعل."
}

@ -76,7 +76,7 @@
"userRoleOrTitle": "User role or title",
"codeSentToEmail": "Code is sent to email",
"number": "Number",
"english": "عربي",
"english": "English",
"title": "Hello",
"msg": "Hello {} in the {} world ",
"msg_named": "{} are written in the {lang} language",
@ -561,12 +561,11 @@
"termPrivacy": "Term & Privacy",
"inviteFriends": "Invite Friends",
"more": "More",
"language": "Language",
"mySubscriptions": "My Subscriptions",
"subscriptions": "Subscriptions",
"defineLicenses": "Define Licenses",
"logOut": "Log Out",
"customer": "Customer",
"accept": "Accept",
"amountVAR": "Amount",
"requestAlreadyInProgress": "This request is already in progress."
}

@ -1,5 +1,6 @@
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:mc_common_app/models/general_models/post_params_model.dart';
import 'package:mc_common_app/models/subscriptions_models/provider_subscription_model.dart';
import 'package:mc_common_app/models/user_models/user.dart';
import 'package:mc_common_app/utils/enums.dart';
@ -44,4 +45,12 @@ class AppState {
set setCurrentLocation(v) => currentLocation = v;
LatLng get getCurrentLocation => currentLocation;
List<ProviderSubscriptionModel>? _providerSubscription;
List<ProviderSubscriptionModel> get getproviderSubscription => _providerSubscription!;
set setproviderSubscription(List<ProviderSubscriptionModel> value) {
_providerSubscription = value;
}
}

@ -30,6 +30,7 @@ class ApiConsts {
static String ChangeEmail = "${baseUrlServices}api/Account/ChangeEmail";
static String EmailVerify = "${baseUrlServices}api/Account/EmailVerify";
static String EmailVerifyOTPVerify = "${baseUrlServices}api/Account/EmailVerifyOTPVerify";
static String LogoutUser = "${baseUrlServices}api/Account/Logout";
static String UpdateUserImage = "${baseUrlServices}api/User_UpdateProfileImage";
static String GetUserImage = "${baseUrlServices}api/ProfileImage";
@ -291,4 +292,5 @@ class MyLocales {
class MyFonts {
static const poppinsFont = "packages/mc_common_app/Poppins";
static const gessTwoFont = "packages/mc_common_app/GessTwo";
}

@ -92,7 +92,7 @@ class CodegenLoader extends AssetLoader{
"userRoleOrTitle": "عنوان المستخدم",
"codeSentToEmail": "تم ارسال الرمز للايميل",
"number": "موبايل",
"english": "English",
"english": "عربي",
"title": "مرحبًا",
"msg": "Hello {} in the {} world ",
"msg_named": "{} are written in the {lang} language",
@ -507,7 +507,7 @@ class CodegenLoader extends AssetLoader{
"submitAd": "إرسال الإعلان",
"selectAdType": "اختر نوع الإعلان",
"validUntilSubscriptionExpiration": "صالح حتى انتهاء الاشتراك",
"adsRemaining": "الإعلانات المتبقية",
"adsRemainingVar": "الإعلانات المتبقية",
"youLeftAdsGivenSubscription": "لقد بقي لديك 05 من 50 إعلانًا في الاشتراك.",
"updateSubscription": "تحديث الاشتراك",
"workInProgress": "العمل جارٍ",
@ -577,13 +577,14 @@ class CodegenLoader extends AssetLoader{
"inviteFriends": "دعوة الأصدقاء",
"more": "المزيد",
"language": "اللغة",
"mySubscriptions": "اشتراكاتي",
"mySubscription": "اشتراكاتي",
"subscriptions": "الاشتراكات",
"defineLicenses": "تحديد التراخيص",
"logOut": "تسجيل الخروج",
"customer": "العميل",
"accept": "قبول",
"requestAlreadyInProgress": "هذا الطلب قيد التقدم بالفعل."
"amountVAR": "كمية"
};
static const Map<String,dynamic> en_US = {
"firstTimeLogIn": "First Time Log In",
@ -663,7 +664,7 @@ static const Map<String,dynamic> en_US = {
"userRoleOrTitle": "User role or title",
"codeSentToEmail": "Code is sent to email",
"number": "Number",
"english": "عربي",
"english": "English",
"title": "Hello",
"msg": "Hello {} in the {} world ",
"msg_named": "{} are written in the {lang} language",
@ -1079,7 +1080,7 @@ static const Map<String,dynamic> en_US = {
"submitAd": "Submit Ad",
"selectAdType": "Select Ad Type",
"validUntilSubscriptionExpiration": "Valid Until Subscription Expiration",
"adsRemaining ": "Ads Remaining",
"adsRemainingVar ": "Ads Remaining",
"youLeftAdsGivenSubscription": "You have left with 05 out of 50 ads given in the subscription.",
"updateSubscription": "Update Subscription",
"workInProgress": "Work In Progress",
@ -1149,12 +1150,13 @@ static const Map<String,dynamic> en_US = {
"inviteFriends": "Invite Friends",
"more": "More",
"language": "Language",
"mySubscriptions": "My Subscriptions",
"mySubscriptions": "My Subscription",
"subscriptions": "Subscriptions",
"defineLicenses": "Define Licenses",
"logOut": "Log Out",
"customer": "Customer",
"accept": "Accept",
"amountVAR": "Amount"
"requestAlreadyInProgress": "This request is already in progress."
};
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": ar_SA, "en_US": en_US};

@ -470,7 +470,7 @@ abstract class LocaleKeys {
static const submitAd = 'submitAd';
static const selectAdType = 'selectAdType';
static const validUntilSubscriptionExpiration = 'validUntilSubscriptionExpiration';
static const adsRemaining = 'adsRemaining';
static const adsRemainingVar = 'adsRemainingVar';
static const youLeftAdsGivenSubscription = 'youLeftAdsGivenSubscription';
static const updateSubscription = 'updateSubscription';
static const workInProgress = 'workInProgress';
@ -540,12 +540,13 @@ abstract class LocaleKeys {
static const inviteFriends = 'inviteFriends';
static const more = 'more';
static const language = 'language';
static const mySubscriptions = 'mySubscriptions';
static const mySubscription = 'mySubscription';
static const subscriptions = 'subscriptions';
static const defineLicenses = 'defineLicenses';
static const logOut = 'logOut';
static const customer = 'customer';
static const accept = 'accept';
static const amountVAR = 'amountVAR';
static const requestAlreadyInProgress = 'requestAlreadyInProgress';
}

@ -0,0 +1,97 @@
import 'dart:convert';
class ProviderSubscriptionModel {
int? id;
int? subscriptionAppliedId;
int? serviceProviderId;
String? subscriptionName;
String? subscriptionDescription;
DateTime? dateStart;
DateTime? dateEnd;
int? branchesRemaining;
int? subUsersRemaining;
int? subscriptionID;
int? adsRemaining;
bool? isExpired;
bool? isActive;
bool? isUpgradeNow;
bool? isUpgradeLater;
bool? isTrialSubscription;
dynamic currentSubscription;
int? totalBranches;
int? totalSubUsers;
int? totalAds;
ProviderSubscriptionModel({
this.id,
this.subscriptionAppliedId,
this.serviceProviderId,
this.subscriptionName,
this.subscriptionDescription,
this.dateStart,
this.dateEnd,
this.branchesRemaining,
this.subUsersRemaining,
this.adsRemaining,
this.isExpired,
this.isActive,
this.isUpgradeNow,
this.isUpgradeLater,
this.isTrialSubscription,
this.currentSubscription,
this.subscriptionID,
this.totalAds,
this.totalBranches,
this.totalSubUsers,
});
factory ProviderSubscriptionModel.fromRawJson(String str) => ProviderSubscriptionModel.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory ProviderSubscriptionModel.fromJson(Map<String, dynamic> json) => ProviderSubscriptionModel(
id: json["id"],
subscriptionAppliedId: json["subscriptionAppliedID"],
serviceProviderId: json["serviceProviderID"],
subscriptionID: json["subscriptionID"],
subscriptionName: json["subscriptionName"],
subscriptionDescription: json["subscriptionDescription"],
dateStart: json["dateStart"] == null ? null : DateTime.parse(json["dateStart"]),
dateEnd: json["dateEnd"] == null ? null : DateTime.parse(json["dateEnd"]),
branchesRemaining: json["branchesRemaining"],
subUsersRemaining: json["subUsersRemaining"],
adsRemaining: json["adsRemaining"],
isExpired: json["isExpired"],
isActive: json["isActive"],
isUpgradeNow: json["isUpgradeNow"],
isUpgradeLater: json["isUpgradeLater"],
isTrialSubscription: json["isTrialSubscription"],
currentSubscription: json["currentSubscription"],
totalBranches: json["totalBranches"],
totalAds: json["totalAds"],
totalSubUsers: json["totalSubUsers"],
);
Map<String, dynamic> toJson() => {
"id": id,
"subscriptionAppliedID": subscriptionAppliedId,
"serviceProviderID": serviceProviderId,
"subscriptionID": subscriptionID,
"subscriptionName": subscriptionName,
"subscriptionDescription": subscriptionDescription,
"dateStart": dateStart?.toIso8601String(),
"dateEnd": dateEnd?.toIso8601String(),
"branchesRemaining": branchesRemaining,
"subUsersRemaining": subUsersRemaining,
"adsRemaining": adsRemaining,
"isExpired": isExpired,
"isActive": isActive,
"isUpgradeNow": isUpgradeNow,
"isUpgradeLater": isUpgradeLater,
"isTrialSubscription": isTrialSubscription,
"currentSubscription": currentSubscription,
"totalAds": totalAds,
"totalSubUsers": totalSubUsers,
"totalBranches": totalBranches,
};
}

@ -8,8 +8,7 @@ import 'package:mc_common_app/extensions/string_extensions.dart';
import '../../utils/enums.dart';
Subscription subscriptionFromJson(String str) =>
Subscription.fromJson(json.decode(str));
Subscription subscriptionFromJson(String str) => Subscription.fromJson(json.decode(str));
String subscriptionToJson(Subscription data) => json.encode(data.toJson());
@ -26,23 +25,17 @@ class SubscriptionModel {
List<Subscription>? data;
String? message;
factory SubscriptionModel.fromJson(Map<String, dynamic> json) =>
SubscriptionModel(
factory SubscriptionModel.fromJson(Map<String, dynamic> json) => SubscriptionModel(
messageStatus: json["messageStatus"],
totalItemsCount: json["totalItemsCount"],
data: json["data"] == null
? []
: List<Subscription>.from(
json["data"]!.map((x) => Subscription.fromJson(x))),
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())),
"data": data == null ? [] : List<dynamic>.from(data!.map((x) => x.toJson())),
"message": message,
};
}
@ -69,6 +62,7 @@ class Subscription {
this.isExpired,
this.isActive,
this.subscriptionTypeEnum,
this.isMyCurrentPackage,
});
int? id;
@ -91,6 +85,7 @@ class Subscription {
bool? isExpired;
bool? isActive;
SubscriptionTypeEnum? subscriptionTypeEnum;
bool? isMyCurrentPackage;
factory Subscription.fromJson(Map<String, dynamic> json) => Subscription(
id: json["id"],
@ -107,16 +102,13 @@ class Subscription {
countryName: json["countryName"],
isSubscribed: json["isSubscribed"],
subscriptionAppliedId: json["subscriptionAppliedID"],
serviceProviderId:
json["serviceProviderID"],
dateStart:
json["dateStart"] == null ? null : DateTime.parse(json["dateStart"]),
serviceProviderId: json["serviceProviderID"],
dateStart: json["dateStart"] == null ? null : DateTime.parse(json["dateStart"]),
dateEnd: json["dateEnd"] == null ? null : DateTime.parse(json["dateEnd"]),
isExpired: json["isExpired"],
isActive: json["isActive"],
subscriptionTypeEnum: json["subscriptionType"] == null
? null
: ((json['subscriptionType']) as int).toSubscriptionTypeEnum());
isMyCurrentPackage: false,
subscriptionTypeEnum: json["subscriptionType"] == null ? null : ((json['subscriptionType']) as int).toSubscriptionTypeEnum());
Map<String, dynamic> toJson() => {
"id": id,

@ -191,7 +191,7 @@ class AppointmentRepoImp implements AppointmentRepo {
queryParameters: map,
ApiConsts.serviceProvidersAppointmentGet,
);
List<AppointmentListModel> appointmentList = List.generate(genericRespModel.data.length, (index) => AppointmentListModel.fromJson(genericRespModel.data[index]));
List<AppointmentListModel> appointmentList = await List.generate(genericRespModel.data.length, (index) => AppointmentListModel.fromJson(genericRespModel.data[index]));
return appointmentList;
}

@ -6,6 +6,7 @@ import 'package:mc_common_app/models/general_models/generic_resp_model.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/models/subscriptions_models/branch_user_selection_model.dart';
import 'package:mc_common_app/models/subscriptions_models/provider_subscription_model.dart';
import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart';
import 'package:mc_common_app/models/user_models/branch_user.dart';
@ -14,22 +15,23 @@ abstract class SubscriptionRepo {
Future<SubscriptionModel> getMySubscriptions(String? serviceProviderID);
Future<SubscriptionModel> getSubscriptionBySP(
String? serviceProviderID, bool isRenew);
Future<List<ProviderSubscriptionModel>> getProviderSubscription({String? serviceProviderID});
Future<MResponse> calculationUpgradePrice(
String? serviceProviderID, String? newSubscription);
Future<SubscriptionModel> getSubscriptionBySP(String? serviceProviderID, bool isRenew);
Future<MResponse> calculationUpgradePrice(String? serviceProviderID, String? newSubscription);
Future<MResponse> payForProviderSubscription(Map<String, dynamic> map);
Future<List<BranchSelectionModel>> getSPBranchUser_Get(
Map<String, String> map);
Future<List<BranchSelectionModel>> getSPBranchUser_Get(Map<String, String> map);
}
class SubscriptionRepoImp extends SubscriptionRepo {
ApiClient apiClient = injector.get<ApiClient>();
AppState appState = injector.get<AppState>();
@override
Future<SubscriptionModel> getAllSubscriptions(
String? serviceProviderID) async {
Future<SubscriptionModel> getAllSubscriptions(String? serviceProviderID) async {
String t = AppState().getUser.data!.accessToken ?? "";
Map<String, String> queryParameters = {};
if (serviceProviderID != null) {
@ -38,16 +40,11 @@ class SubscriptionRepoImp extends SubscriptionRepo {
};
}
return await injector.get<ApiClient>().getJsonForObject(
(json) => SubscriptionModel.fromJson(json),
ApiConsts.getAllSubscriptions,
token: t,
queryParameters: queryParameters);
return await injector.get<ApiClient>().getJsonForObject((json) => SubscriptionModel.fromJson(json), ApiConsts.getAllSubscriptions, token: t, queryParameters: queryParameters);
}
@override
Future<SubscriptionModel> getSubscriptionBySP(
String? serviceProviderID, bool isRenew) async {
Future<SubscriptionModel> getSubscriptionBySP(String? serviceProviderID, bool isRenew) async {
String t = AppState().getUser.data!.accessToken ?? "";
Map<String, String> queryParameters = {};
if (serviceProviderID != null) {
@ -66,8 +63,7 @@ class SubscriptionRepoImp extends SubscriptionRepo {
}
@override
Future<MResponse> calculationUpgradePrice(
String? serviceProviderID, String? newSubscription) async {
Future<MResponse> calculationUpgradePrice(String? serviceProviderID, String? newSubscription) async {
String t = AppState().getUser.data!.accessToken ?? "";
Map<String, String> queryParameters = {};
if (serviceProviderID != null) {
@ -98,17 +94,15 @@ class SubscriptionRepoImp extends SubscriptionRepo {
}
@override
Future<List<BranchSelectionModel>> getSPBranchUser_Get(
Map<String, String> map) async {
Future<List<BranchSelectionModel>> getSPBranchUser_Get(Map<String, String> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
GenericRespModel genericRespModel =
await injector.get<ApiClient>().getJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getSPBranchUser_Get,
token: t,
queryParameters: map,
);
GenericRespModel genericRespModel = await injector.get<ApiClient>().getJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getSPBranchUser_Get,
token: t,
queryParameters: map,
);
List<BranchSelectionModel> branchList = [];
@ -117,36 +111,23 @@ class SubscriptionRepoImp extends SubscriptionRepo {
List<BranchUser> branchUsers = [];
// List<BranchUsersDatum>.from(json["data"]!.map((x) => BranchUsersDatum.fromJson(x))
branches = List<BranchDetailModel>.from(genericRespModel.data["branches"]
["data"]!
.map((x) => BranchDetailModel.fromJson(x)));
branchUsers = List<BranchUser>.from(genericRespModel.data["branchUsers"]
["data"]!
.map((x) => BranchUser.fromJson(x)));
branches = List<BranchDetailModel>.from(genericRespModel.data["branches"]["data"]!.map((x) => BranchDetailModel.fromJson(x)));
branchUsers = List<BranchUser>.from(genericRespModel.data["branchUsers"]["data"]!.map((x) => BranchUser.fromJson(x)));
for (int i = 0; i < branches.length; i++) {
List<UserSelectionModel> availableUsers = [];
for (int j = 0; j < branchUsers.length; j++) {
if (branches[i].id == branchUsers[j].serviceProviderBranchID) {
availableUsers.add(UserSelectionModel(
userId: branchUsers[j].id,
userName:
("${branchUsers[j].firstName ?? ""} ${branchUsers[j].lastName}"),
isSelected: false));
availableUsers.add(UserSelectionModel(userId: branchUsers[j].id, userName: ("${branchUsers[j].firstName ?? ""} ${branchUsers[j].lastName}"), isSelected: false));
}
}
branchList.add(BranchSelectionModel(
branchId: branches[i].id ?? 0,
branchName: branches[i].branchName ?? "",
isSelected: false,
usersList: availableUsers));
branchList.add(BranchSelectionModel(branchId: branches[i].id ?? 0, branchName: branches[i].branchName ?? "", isSelected: false, usersList: availableUsers));
}
}
return branchList;
}
@override
Future<SubscriptionModel> getMySubscriptions(
String? serviceProviderID) async {
Future<SubscriptionModel> getMySubscriptions(String? serviceProviderID) async {
String t = AppState().getUser.data!.accessToken ?? "";
Map<String, String> queryParameters = {};
if (serviceProviderID != null) {
@ -154,12 +135,46 @@ class SubscriptionRepoImp extends SubscriptionRepo {
"ID": serviceProviderID,
};
}
return await injector.get<ApiClient>().getJsonForObject(
(json) => SubscriptionModel.fromJson(json),
ApiConsts.getAllSubscriptions,
token: t,
queryParameters: queryParameters);
return await injector.get<ApiClient>().getJsonForObject((json) => SubscriptionModel.fromJson(json), ApiConsts.getAllSubscriptions, token: t, queryParameters: queryParameters);
}
@override
Future<List<ProviderSubscriptionModel>> getProviderSubscription({String? serviceProviderID}) async {
Map<String, String> queryParameters = {};
if (serviceProviderID != null) {
queryParameters = {
"ServiceProviderID": serviceProviderID,
"IsActiveSubscriptionForProvider": "true",
};
}
GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
token: appState.getUser.data!.accessToken,
(json) => GenericRespModel.fromJson(json),
ApiConsts.getMySubscriptions,
queryParameters: queryParameters,
);
List<ProviderSubscriptionModel> providerSubList = List.generate(adsGenericModel.data.length, (index) => ProviderSubscriptionModel.fromJson(adsGenericModel.data[index]));
return providerSubList;
}
// @override
// Future<SubscriptionModel> getProviderSubscription(
// String? serviceProviderID) async {
// String t = AppState().getUser.data!.accessToken ?? "";
// Map<String, String> queryParameters = {};
// if (serviceProviderID != null) {
// queryParameters = {
// "ID": serviceProviderID,
// };
// }
//
//
// return await injector.get<ApiClient>().getJsonForObject(
// (json) => SubscriptionModel.fromJson(json),
// ApiConsts.getMySubscriptions,
// token: t,
// queryParameters: queryParameters);
// }
}

@ -71,6 +71,8 @@ abstract class UserRepo {
Future<ImageResponse> getUserImage(String image);
Future<Response> logoutUser();
Future<String> updateUserToken();
}
@ -275,7 +277,12 @@ class UserRepoImp implements UserRepo {
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token $t");
return await injector.get<ApiClient>().postJsonForObject((json) => ImageResponse.fromJson(json), ApiConsts.UpdateUserImage, postParams, token: t,);
return await injector.get<ApiClient>().postJsonForObject(
(json) => ImageResponse.fromJson(json),
ApiConsts.UpdateUserImage,
postParams,
token: t,
);
}
@override
@ -303,4 +310,10 @@ class UserRepoImp implements UserRepo {
AppState().setUser = user;
return refresh.data!.accessToken ?? "";
}
Future<Response> logoutUser() async {
String t = AppState().getUser.data!.accessToken ?? "";
var postParams = {"token": AppState().getUser.data!.accessToken ?? ""};
return await injector.get<ApiClient>().postJsonForResponse(ApiConsts.LogoutUser, postParams, token: t);
}
}

@ -5,14 +5,14 @@ import 'colors.dart';
class AppTheme {
static getTheme({required isArabic}) {
return ThemeData(
fontFamily: !isArabic ? MyFonts.poppinsFont : null,
fontFamily: !isArabic ? MyFonts.poppinsFont : MyFonts.gessTwoFont,
primaryColor: primaryColor,
useMaterial3: false,
primaryTextTheme: const TextTheme(
titleLarge: TextStyle(color: Colors.white),
), colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.orange).copyWith(background: Colors.white),
),
colorScheme: ColorScheme.fromSwatch(primarySwatch: Colors.orange).copyWith(background: Colors.white),
);
}
}

@ -69,6 +69,7 @@ class AppointmentsVM extends BaseVM {
List<DropValue> branchCategories = [];
bool isHomeTapped = false;
bool isShowEmptyMessage = false;
List<ServiceAppointmentScheduleModel> serviceAppointmentScheduleList = [];
@ -338,12 +339,31 @@ class AppointmentsVM extends BaseVM {
// }).toList();
}
// Future<void> getMyAppointments() async {
// setState(ViewState.busy);
//
// myAppointments =
// await appointmentRepo.getMyAppointmentsForCustomersByFilters();
// myFilteredAppointments = myAppointments;
// myUpComingAppointments = myAppointments
// .where((element) =>
// element.appointmentStatusEnum == AppointmentStatusEnum.booked)
// .toList();
// applyFilterOnAppointmentsVM(
// appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
// if (myUpComingAppointments.isEmpty) {
// isShowEmptyMessage = true;
// }
// setState(ViewState.idle);
// notifyListeners();
// }
Future<void> getMyAppointments({bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
myAppointments = await appointmentRepo.getMyAppointmentsForCustomersByFilters();
// myFilteredAppointments = myAppointments;
myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.confirmed).toList();
myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.booked || element.appointmentStatusEnum == AppointmentStatusEnum.confirmed ).toList();
setState(ViewState.idle);
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments);
notifyListeners();
@ -365,13 +385,13 @@ class AppointmentsVM extends BaseVM {
}
}
Future<void> getMyAppointmentsForProvider(Map<String, dynamic> map, {bool isNeedToRebuild = false}) async {
if (isNeedToRebuild) setState(ViewState.busy);
Future<void> getMyAppointmentsForProvider(
Map<String, dynamic> map,
) async {
setState(ViewState.busy);
myAppointments = await appointmentRepo.getMyAppointmentsForProvider(map);
myFilteredAppointments = myAppointments;
myUpComingAppointments = myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.booked).toList();
myUpComingAppointments = await myAppointments.where((element) => element.appointmentStatusEnum == AppointmentStatusEnum.confirmed).toList();
applyFilterOnAppointmentsVM(appointmentStatusEnum: AppointmentStatusEnum.allAppointments, isNeedCustomerFilter: true);
setState(ViewState.idle);
}
@ -417,7 +437,7 @@ class AppointmentsVM extends BaseVM {
updateCheckBoxInMergeRequest(int currentIndex) {
myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList![currentIndex].isSelected =
!(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false);
!(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList?[currentIndex].isSelected ?? false);
int count = countSelected(myFilteredAppointments2[selectedAppointmentIndex].customerAppointmentList ?? []);
if (count > 1)
@ -428,10 +448,7 @@ class AppointmentsVM extends BaseVM {
}
int countSelected(List<AppointmentListModel> appointments) {
return appointments
.where((appointment) => appointment.isSelected == true)
.toList()
.length;
return appointments.where((appointment) => appointment.isSelected == true).toList().length;
}
updateSelectedAppointmentDate({required int dateIndex, required int scheduleIndex}) {
@ -598,14 +615,13 @@ class AppointmentsVM extends BaseVM {
Column(
children: List.generate(
selectedService.serviceItems!.length,
(index) =>
Row(
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),
],
),
(index) => Row(
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),
],
),
),
),
Row(

@ -350,8 +350,7 @@ class ServiceVM extends BaseVM {
setState(ViewState.idle);
}
Future<void> getAllCountriesList(
BranchDetailModel? branchData, String countryCode) async {
Future<void> getAllCountriesList(BranchDetailModel? branchData, String countryCode) async {
cities = null;
country = null;
setState(ViewState.busy);
@ -386,8 +385,7 @@ class ServiceVM extends BaseVM {
setState(ViewState.idle);
}
Future<void> getAllCities(
BranchDetailModel? branchData, String countryCode) async {
Future<void> getAllCities(BranchDetailModel? branchData, String countryCode) async {
setState(ViewState.busy);
citiesDropList = [];
cities = null;
@ -432,16 +430,15 @@ class ServiceVM extends BaseVM {
cityId.toString(), address, latitude.toString(), longitude.toString());
}
Future<MResponse> updateBranch(
int id,
String branchName,
String branchDescription,
String cityId,
String address,
String latitude,
String longitude, {
bool isNeedToDelete = true,
}) async {
Future<MResponse> updateBranch(int id,
String branchName,
String branchDescription,
String cityId,
String address,
String latitude,
String longitude, {
bool isNeedToDelete = true,
}) async {
return await branchRepo.updateBranch(
id ?? 0,
branchName,
@ -488,10 +485,10 @@ class ServiceVM extends BaseVM {
DropValue(
element.id ?? 0,
((element.categoryName!.isEmpty
? "N/A"
: countryCode == "SA"
? element.categoryNameN
: element.categoryName) ??
? "N/A"
: countryCode == "SA"
? element.categoryNameN
: element.categoryName) ??
"N/A"),
"",
),
@ -551,8 +548,7 @@ class ServiceVM extends BaseVM {
List<ServiceModel>? matchedServices;
bool isAllSelected = false;
Future<void> getAllMatchedServices(
int oldBranchId, int newBranchId, int categoryId) async {
Future<void> getAllMatchedServices(int oldBranchId, int newBranchId, int categoryId) async {
matchedServices = null;
final MResponse response = await branchRepo.getMatchedServices(
oldBranchId, newBranchId, categoryId);

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/subscriptions_models/branch_user_selection_model.dart';
import 'package:mc_common_app/models/subscriptions_models/provider_subscription_model.dart';
import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
@ -19,6 +20,7 @@ class SubscriptionsVM extends BaseVM {
late DropValue selectedMothlyTab;
List<DropValue> monthlyTabs = [];
late SubscriptionModel allSubscriptions;
List<ProviderSubscriptionModel> mySubscriptionsBySp = [];
List<Subscription> tempSubscriptions = [];
//My Subscriptions
@ -33,10 +35,11 @@ class SubscriptionsVM extends BaseVM {
var idSet = <int>{};
for (var d in allSubscriptions.data ?? []) {
if (idSet.add(d.durationDays ?? 0)) {
monthlyTabs.add(DropValue(d.durationDays, _convertDaysToMonths(d.durationDays ?? 0), ""));
monthlyTabs.add(DropValue(d.durationDays, _convertDaysToMonths(d.durationDays ?? 0), "", isEnabled: false));
}
}
monthlyTabs.sort((a, b) => a.value.compareTo(b.value));
monthlyTabs.first.isEnabled = true;
selectedMothlyTab = monthlyTabs.first;
filterSubscriptions();
setState(ViewState.idle);
@ -54,11 +57,13 @@ class SubscriptionsVM extends BaseVM {
var idSet = <int>{};
for (var d in allSubscriptions.data ?? []) {
if (idSet.add(d.durationDays ?? 0)) {
monthlyTabs.add(DropValue(d.durationDays, _convertDaysToMonths(d.durationDays ?? 0), ""));
monthlyTabs.add(DropValue(d.durationDays, _convertDaysToMonths(d.durationDays ?? 0), "", isEnabled: false));
}
}
monthlyTabs.sort((a, b) => a.value.compareTo(b.value));
monthlyTabs.first.isEnabled = true;
selectedMothlyTab = monthlyTabs.first;
filterSubscriptions();
setState(ViewState.idle);
} else {
@ -110,17 +115,12 @@ class SubscriptionsVM extends BaseVM {
return mResponse;
}
Future<MResponse> createSubscriptionOrder(int subscriptionId, bool isStartNow, bool isReview, String amount, {bool isDegrade = false, List<int>? listOfBranches, List<int>? listOfUsers}) async {
Future<MResponse> createSubscriptionOrder(int subscriptionId, bool isStartNow, bool isRenew, {bool isDegrade = false, List<int>? listOfBranches, List<int>? listOfUsers}) async {
Map<String, dynamic> map = {
// "id": subscription.id.toString(),
// "payFortOrderID": 0,
"providerID": AppState().getUser.data?.userInfo?.providerId.toString() ?? "",
"subscriptionID": subscriptionId.toString(),
"isStartNow": isStartNow.toString(),
"subscriptionAmount": amount,
"isRenew": isReview.toString()
// "listOfBranches": [],
// "listOfUsers": []
"isRenew": isRenew.toString()
};
MResponse mResponse = await subscriptionRepo.payForProviderSubscription(map);
return mResponse;
@ -159,6 +159,9 @@ class SubscriptionsVM extends BaseVM {
if (selectedMothlyTab.id == element.durationDays) {
tempSubscriptions.add(element);
}
if (element.id == AppState().getproviderSubscription.first.subscriptionID) {
element.isMyCurrentPackage = true;
}
}
}
@ -168,6 +171,7 @@ class SubscriptionsVM extends BaseVM {
setState(ViewState.busy);
// allSubscriptions = await subscriptionRepo.getAllSubscriptions(serviceProviderID);
allSubscriptions = await subscriptionRepo.getMySubscriptions(serviceProviderID);
if (allSubscriptions.messageStatus == 1) {
// allSubscriptions.data!.sort((a, b) => a.value.compareTo(b.value));
setState(ViewState.idle);
@ -175,4 +179,14 @@ class SubscriptionsVM extends BaseVM {
setState(ViewState.error);
}
}
// My Provider Subscription
getMySubscriptionsBySP(String? serviceProviderID) async {
setState(ViewState.busy);
if (mySubscriptionsBySp.isEmpty) {
mySubscriptionsBySp = await subscriptionRepo.getProviderSubscription(serviceProviderID: serviceProviderID);
AppState().setproviderSubscription = mySubscriptionsBySp;
}
setState(ViewState.idle);
}
}

@ -1,16 +1,10 @@
import 'dart:convert';
import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart';
import 'package:huawei_fido/huawei_fido.dart';
import 'package:image_picker/image_picker.dart';
import 'package:http/src/response.dart';
import 'package:local_auth/local_auth.dart';
import 'package:logger/logger.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';
@ -27,7 +21,6 @@ import 'package:mc_common_app/models/user_models/confirm_password.dart';
import 'package:mc_common_app/models/user_models/country.dart';
import 'package:mc_common_app/models/user_models/forget_password_otp_compare.dart';
import 'package:mc_common_app/models/user_models/forget_password_otp_request.dart';
import 'package:mc_common_app/models/user_models/image_response.dart';
import 'package:mc_common_app/models/user_models/login_password.dart';
import 'package:mc_common_app/models/user_models/register_user.dart';
import 'package:mc_common_app/models/user_models/user.dart';
@ -163,7 +156,8 @@ class UserVM extends BaseVM {
}
}
Future<void> performCompleteProfile(BuildContext context, {
Future<void> performCompleteProfile(
BuildContext context, {
required String password,
required String confirmPassword,
required String firstName,
@ -350,13 +344,10 @@ class UserVM extends BaseVM {
Future<void> performBasicOtpLoginSelectionPage(BuildContext context, {required String userToken, required AppType appType, String? loginType}) async {
if (loginType == "3" || loginType == "4") {
Utils.showLoading(context);
//Utils.showLoading(context);
LoginPasswordRespModel user = await userRepo.loginV2OTP(userToken, loginType!);
Utils.hideLoading(context);
if (user.messageStatus == 1) {
Utils.showLoading(context);
Response response2 = await userRepo.loginV2OTPVerify(user.data!.userToken ?? "", "9999");
Utils.hideLoading(context);
RegisterUserRespModel verifiedUser = RegisterUserRespModel.fromJson(jsonDecode(response2.body));
if (verifiedUser.messageStatus == 1) {
User user = User.fromJson(jsonDecode(response2.body));
@ -370,7 +361,6 @@ class UserVM extends BaseVM {
navigateReplaceWithName(context, AppRoutes.dashboard);
} else {
Utils.showToast(LocaleKeys.onlyProviderApp.tr());
//("Sorry, Only Customer's can log in this app");
}
} else if (user.data!.userInfo!.roleId == 4) {
if (user.data!.userInfo!.roleId == 4) {
@ -389,9 +379,9 @@ class UserVM extends BaseVM {
}
}
} else {
Utils.showLoading(context);
// Utils.showLoading(context);
LoginPasswordRespModel user = await userRepo.loginV2OTP(userToken, "1");
Utils.hideLoading(context);
// Utils.hideLoading(context);
if (user.messageStatus == 1) {
showMDialog(context, child: OtpDialog(
onClick: (String code) async {
@ -522,8 +512,8 @@ class UserVM extends BaseVM {
type == ClassType.NUMBER && countryCode != null
? countryCode + phoneNum
: type == ClassType.NUMBER && countryCode == null
? phoneNum
: phoneNum,
? phoneNum
: phoneNum,
password);
Utils.hideLoading(context);
LoginPasswordRespModel user = LoginPasswordRespModel.fromJson(jsonDecode(response.body));
@ -531,8 +521,8 @@ class UserVM extends BaseVM {
SharedPrefManager.setPhoneOrEmail(type == ClassType.NUMBER && countryCode != null
? countryCode + phoneNum
: type == ClassType.NUMBER && countryCode == null
? phoneNum
: phoneNum);
? phoneNum
: phoneNum);
SharedPrefManager.setUserPassword(password);
navigateReplaceWithName(context, AppRoutes.loginMethodSelection, arguments: user.data!.userToken);
} else {
@ -628,6 +618,7 @@ class UserVM extends BaseVM {
String uName = await SharedPrefManager.getPhoneOrEmail();
String pass = await SharedPrefManager.getUserPassword();
if (!loginOtherAccount && uName.isNotEmpty && pass.isNotEmpty) {
getAvailBio();
if (uName.isNum()) {
performBasicOtpLoginWithPasswordPage(context, type: ClassType.NUMBER, countryCode: null, phoneNum: uName, password: pass);
}
@ -642,4 +633,28 @@ class UserVM extends BaseVM {
_loginOtherAccount = true;
navigateReplaceWithName(context, AppRoutes.loginWithPassword);
}
void changeLanguage(BuildContext context) {
if (EasyLocalization.of(context)?.currentLocale?.countryCode == "SA") {
context.setLocale(const Locale("en", "US"));
} else {
context.setLocale(const Locale('ar', 'SA'));
}
notifyListeners();
}
void logout(BuildContext context) async {
Response value = await userRepo.logoutUser();
if (value.body.isNotEmpty) {
print(value.body);
print("Logout");
}
SharedPrefManager.setPhoneOrEmail("");
SharedPrefManager.setUserPassword("");
if (AppState().getUser.data!.userInfo!.userLocalImage != null) {
AppState().getUser.data!.userInfo!.userLocalImage = null;
AppState().getUser.data!.userInfo!.userImageUrl = null;
}
navigateReplaceWithNameUntilRoute(context, AppRoutes.registerSelection);
}
}

@ -245,7 +245,7 @@ class AdDurationReview extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleDetailWidget(type: LocaleKeys.amount.tr(), text: adVM.specialServiceCards[index].serviceSelectedId!.itemPrice),
SingleDetailWidget(type: LocaleKeys.amountVAR.tr(), text: adVM.specialServiceCards[index].serviceSelectedId!.itemPrice),
],
),
),

@ -157,7 +157,7 @@ class SelectAdTypeView extends StatelessWidget {
Row(
children: [
"5 of 10 ".toText(fontSize: 29, isBold: true, letterSpacing: 0, height: 1),
LocaleKeys.adsRemaining.tr().toText(fontSize: 17, color: MyColors.lightTextColor, isBold: true),
LocaleKeys.adsRemainingVar.tr().toText(fontSize: 17, color: MyColors.lightTextColor, isBold: true),
],
),
Text.rich(

@ -219,7 +219,7 @@ class ReviewAppointment extends StatelessWidget {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocaleKeys.amount
LocaleKeys.amountVAR
.tr()
.toText(fontSize: 16, isBold: true),
Row(

@ -1,107 +1,148 @@
import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.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/models/appointments_models/appointment_list_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/view_models/dashboard_view_model_customer.dart';
import 'package:mc_common_app/views/advertisement/custom_add_button.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
//TODO: Need to make onTapped dynamic
class CustomerAppointmentSliderWidget extends StatelessWidget {
final List<AppointmentListModel> myUpComingAppointments;
bool isNeedToShowEmptyMessage;
Function()? onAppointmentClick;
Function(AppointmentListModel)? onAppointmentClick;
CustomerAppointmentSliderWidget({Key? key,
required this.myUpComingAppointments,
this.isNeedToShowEmptyMessage = false,
this.onAppointmentClick})
: super(key: key);
CustomerAppointmentSliderWidget({Key? key, this.onAppointmentClick}) : super(key: key);
@override
Widget build(BuildContext context) {
if (myUpComingAppointments.isEmpty) {
if (isNeedToShowEmptyMessage)
return "No Upcoming Appointment Available".toText().paddingAll(21);
return CustomAddButton(
needsBorder: true,
bgColor: MyColors.white,
onTap: () => context.read<DashboardVmCustomer>().onNavbarTapped(0),
text: "Add New Appointment",
icon: Container(
height: 24,
width: 24,
decoration: const BoxDecoration(
shape: BoxShape.circle, color: MyColors.darkTextColor),
child: const Icon(Icons.add, color: MyColors.white),
),
).padding(EdgeInsets.symmetric(vertical: 10, horizontal: 21));
return Container(
height: 86,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 24,
width: 24,
decoration: BoxDecoration(
shape: BoxShape.circle, color: MyColors.darkTextColor),
child: Icon(
Icons.add,
color: MyColors.white,
),
),
SizedBox(width: 10),
"Add New Appointment".toText(
fontSize: 15,
isBold: true,
color: MyColors.lightTextColor,
),
],
),
).onPress(() {}).toWhiteContainer(
width: double.infinity,
margin: EdgeInsets.symmetric(horizontal: 21, vertical: 10));
}
Widget getCorouselWidget(AppType appType, AppointmentsVM appointmentsVM) {
return CarouselSlider.builder(
options: CarouselOptions(
height: 140,
height: appType == AppType.provider ? 110 : 140,
viewportFraction: 1.0,
enlargeCenterPage: false,
enableInfiniteScroll: false,
),
itemCount: myUpComingAppointments.length,
itemBuilder: (BuildContext context, int itemIndex, int pageViewIndex) =>
BuildAppointmentContainerForCustomer(
isForHome: true,
appointmentListModel: myUpComingAppointments[itemIndex],
onTapped: isNeedToShowEmptyMessage
? onAppointmentClick!
: () =>
navigateWithName(context, AppRoutes.appointmentDetailView,
arguments: myUpComingAppointments[itemIndex]),
),
itemCount: appointmentsVM.myUpComingAppointments.length,
itemBuilder: (BuildContext context, int itemIndex, int pageViewIndex) => BuildAppointmentContainerForCustomer(
isForHome: appType == AppType.provider,
appointmentListModel: appointmentsVM.myUpComingAppointments[itemIndex],
onTapped: () {
if (appType == AppType.provider) {
onAppointmentClick!(appointmentsVM.myUpComingAppointments[itemIndex]);
} else {
navigateWithName(context, AppRoutes.appointmentDetailView, arguments: appointmentsVM.myUpComingAppointments[itemIndex]);
}
},
),
);
}
@override
Widget build(BuildContext context) {
return Consumer(builder: (BuildContext context, AppointmentsVM model, Widget? child) {
if (model.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
if (AppState().currentAppType == AppType.provider) {
if (model.myUpComingAppointments.isEmpty) {
return "No Upcoming Appointment Available".toText().paddingAll(21);
} else {
return getCorouselWidget(AppState().currentAppType, model);
}
} else {
if (model.myUpComingAppointments.isEmpty) {
return CustomAddButton(
needsBorder: true,
bgColor: MyColors.white,
onTap: () => context.read<DashboardVmCustomer>().onNavbarTapped(0),
text: "Add New Appointment",
icon: Container(
height: 24,
width: 24,
decoration: const BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor),
child: const Icon(Icons.add, color: MyColors.white),
),
).padding(EdgeInsets.symmetric(vertical: 10, horizontal: 21));
} else {
return getCorouselWidget(AppState().currentAppType, model);
}
}
}
});
}
// if (myUpComingAppointments.isEmpty) {
// if (isNeedToShowEmptyMessage)
// return "No Upcoming Appointment Available".toText().paddingAll(21);
// return CustomAddButton(
// needsBorder: true,
// bgColor: MyColors.white,
// onTap: () => context.read<DashboardVmCustomer>().onNavbarTapped(0),
// text: "Add New Appointment",
// icon: Container(
// height: 24,
// width: 24,
// decoration: const BoxDecoration(
// shape: BoxShape.circle, color: MyColors.darkTextColor),
// child: const Icon(Icons.add, color: MyColors.white),
// ),
// ).padding(EdgeInsets.symmetric(vertical: 10, horizontal: 21));
// return Container(
// height: 86,
// child: Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Container(
// height: 24,
// width: 24,
// decoration: BoxDecoration(
// shape: BoxShape.circle, color: MyColors.darkTextColor),
// child: Icon(
// Icons.add,
// color: MyColors.white,
// ),
// ),
// SizedBox(width: 10),
// "Add New Appointment".toText(
// fontSize: 15,
// isBold: true,
// color: MyColors.lightTextColor,
// ),
// ],
// ),
// ).onPress(() {}).toWhiteContainer(
// width: double.infinity,
// margin: EdgeInsets.symmetric(horizontal: 21, vertical: 10));
// }
// return CarouselSlider.builder(
// options: CarouselOptions(
// height: 140,
// viewportFraction: 1.0,
// enlargeCenterPage: false,
// enableInfiniteScroll: false,
// ),
// itemCount: myUpComingAppointments.length,
// itemBuilder: (BuildContext context, int itemIndex, int pageViewIndex) => BuildAppointmentContainerForCustomer(
// isForHome: true,
// appointmentListModel: myUpComingAppointments[itemIndex],
// onTapped: isNeedToShowEmptyMessage ? onAppointmentClick! : () => navigateWithName(context, AppRoutes.appointmentDetailView, arguments: myUpComingAppointments[itemIndex]),
// ),
// );
}
class BuildAppointmentContainerForCustomer extends StatelessWidget {
final bool? isForHome;
final AppointmentListModel? appointmentListModel;
final Function() onTapped;
final Function()? onTapped;
const BuildAppointmentContainerForCustomer({Key? key,
this.isForHome = false,
required this.onTapped,
required this.appointmentListModel})
: super(key: key);
const BuildAppointmentContainerForCustomer({Key? key, this.isForHome = false, this.onTapped, required this.appointmentListModel}) : super(key: key);
Widget showServices(String title, String icon, {bool isMoreText = false}) {
return Row(
@ -121,18 +162,15 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
);
}
List<Widget> buildServicesFromAppointment(
{required AppointmentListModel appointmentListModel}) {
if (appointmentListModel.appointmentServicesList == null ||
appointmentListModel.appointmentServicesList!.isEmpty) {
List<Widget> buildServicesFromAppointment({required AppointmentListModel appointmentListModel}) {
if (appointmentListModel.appointmentServicesList == null || appointmentListModel.appointmentServicesList!.isEmpty) {
return [SizedBox()];
}
if (appointmentListModel.appointmentServicesList!.length == 1) {
return [
showServices(
appointmentListModel
.appointmentServicesList![0].providerServiceDescription,
appointmentListModel.appointmentServicesList![0].providerServiceDescription,
MyAssets.modificationsIcon,
)
];
@ -140,11 +178,7 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
List<Widget> servicesList = List.generate(
2,
(index) =>
showServices(
appointmentListModel
.appointmentServicesList![index].providerServiceDescription,
MyAssets.modificationsIcon),
(index) => showServices(appointmentListModel.appointmentServicesList![index].providerServiceDescription, MyAssets.modificationsIcon),
);
if (appointmentListModel.appointmentServicesList!.length > 1) {
@ -170,33 +204,30 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
children: [
isForHome != null && isForHome!
? Image.asset(
MyAssets.bnCar,
width: 56,
height: 56,
fit: BoxFit.fill,
).toCircle(borderRadius: 100)
MyAssets.bnCar,
width: 56,
height: 56,
fit: BoxFit.fill,
).toCircle(borderRadius: 100)
: Image.asset(
MyAssets.bnCar,
width: 80,
height: 85,
fit: BoxFit.cover,
),
MyAssets.bnCar,
width: 80,
height: 85,
fit: BoxFit.cover,
),
8.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
(appointmentListModel!.providerName ?? "").toText(
color: MyColors.black, isBold: true, fontSize: 16),
(AppState().currentAppType == AppType.provider ? appointmentListModel!.customerName ?? "" : appointmentListModel!.branchName ?? "")
.toText(color: MyColors.black, isBold: true, fontSize: 16),
Row(
children: [
MyAssets.miniClock.buildSvg(height: 12),
2.width,
"${appointmentListModel!.duration ??
""} ${appointmentListModel!.appointmentDate!
.toFormattedDateWithoutTime()}"
.toText(
"${appointmentListModel!.duration ?? ""} ${appointmentListModel!.appointmentDate!.toFormattedDateWithoutTime()}".toText(
color: MyColors.lightTextColor,
fontSize: 12,
),
@ -205,42 +236,38 @@ class BuildAppointmentContainerForCustomer extends StatelessWidget {
9.height,
isForHome != null && isForHome!
? Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"Appointment Details".toText(
color: MyColors.primaryColor,
isUnderLine: true,
isBold: true,
fontSize: 14,
),
const Icon(Icons.arrow_forward),
],
)
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"Appointment Details".toText(
color: MyColors.primaryColor,
isUnderLine: true,
isBold: true,
fontSize: 14,
),
const Icon(Icons.arrow_forward),
],
)
: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: Column(
children: buildServicesFromAppointment(
appointmentListModel:
appointmentListModel!),
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: Column(
children: buildServicesFromAppointment(appointmentListModel: appointmentListModel!),
),
),
const Icon(
Icons.arrow_forward,
),
],
),
),
const Icon(
Icons.arrow_forward,
),
],
),
],
),
),
],
),
],
)
.onPress(onTapped)
.toWhiteContainer(width: double.infinity, allPading: 12),
).onPress(onTapped!).toWhiteContainer(width: double.infinity, allPading: 12),
);
}
}

@ -3,6 +3,7 @@ import 'dart:io';
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/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';
@ -34,8 +35,7 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
// TODO: implement initState
super.initState();
branchVM = Provider.of<ServiceVM>(context, listen: false);
branchVM.getServiceProviderDocument(
AppState().getUser.data!.userInfo!.providerId ?? 0);
branchVM.getServiceProviderDocument(AppState().getUser.data!.userInfo!.providerId ?? 0);
}
@override
@ -74,13 +74,14 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
if (validation(model)) {
updateDocument(model);
} else {
Utils.showToast(LocaleKeys
.allDocumentMandatoryDealershipProvider
.tr());
Utils.showToast(LocaleKeys.allDocumentMandatoryDealershipProvider.tr());
}
} else {
updateDocument(model);
}
Future.delayed(const Duration(seconds: 1), () {
Navigator.of(context).pop();
});
},
),
),
@ -127,27 +128,19 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
),
),
Padding(
padding: const EdgeInsets.only(
left: 20, right: 20, top: 4, bottom: 8),
child: LocaleKeys.enter_licence_detail.tr().toText(
fontSize: 14,
color: MyColors.lightTextColor,
textAlign: TextAlign.center),
padding: const EdgeInsets.only(left: 20, right: 20, top: 4, bottom: 8),
child: LocaleKeys.enter_licence_detail.tr().toText(fontSize: 14, color: MyColors.lightTextColor, textAlign: TextAlign.center),
),
TxtField(
hint: LocaleKeys.description.tr(),
maxLines: 3,
isBackgroundEnabled: true,
),
if ((model.document?.data![index].documentUrl ?? "")
.toString()
.isNotEmpty)
if ((model.document?.data![index].documentUrl ?? "").toString().isNotEmpty)
Column(
children: [
8.height,
(model.document?.data![index].documentUrl ?? "")
.toString()
.toText(
(model.document?.data![index].documentUrl ?? "").toString().toText(
fontSize: 14,
color: MyColors.lightTextColor,
),
@ -163,10 +156,8 @@ class _ProviderLicensePageState extends State<ProviderLicensePage> {
height: 45,
decoration: BoxDecoration(
color: Colors.transparent,
border:
Border.all(color: MyColors.greyACColor, width: 2),
borderRadius:
const BorderRadius.all(Radius.circular(0)),
border: Border.all(color: MyColors.greyACColor, width: 2),
borderRadius: const BorderRadius.all(Radius.circular(0)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,

@ -10,6 +10,7 @@ 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/dashboard_view_model_customer.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';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
@ -40,8 +41,7 @@ class SettingOptionsLanguage extends StatelessWidget {
Column(
children: [
CustomSettingOptionsTile(
leadingWidget:
const Icon(Icons.quickreply_outlined, size: 20),
leadingWidget: const Icon(Icons.quickreply_outlined, size: 20),
titleText: LocaleKeys.requests.tr(),
needBorderBelow: true,
onTap: () {
@ -56,12 +56,10 @@ class SettingOptionsLanguage extends StatelessWidget {
//navigateWithName(context, AppRoutes.settingOptionsInviteFriends),
),
CustomSettingOptionsTile(
leadingWidget:
const Icon(Icons.question_mark_outlined, size: 20),
leadingWidget: const Icon(Icons.question_mark_outlined, size: 20),
titleText: LocaleKeys.help.tr(),
needBorderBelow: true,
onTap: () =>
navigateWithName(context, AppRoutes.settingOptionsHelp),
onTap: () => navigateWithName(context, AppRoutes.settingOptionsHelp),
),
CustomSettingOptionsTile(
leadingWidget: const Icon(Icons.person, size: 20),
@ -73,29 +71,25 @@ class SettingOptionsLanguage extends StatelessWidget {
// Navigator.pop(context);
}),
],
).toWhiteContainer(
width: double.infinity,
pading: const EdgeInsets.all(12),
borderRadius: 0),
).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0),
10.height,
CustomSettingOptionsTile(
leadingWidget: const Icon(Icons.translate, size: 20),
titleText: LocaleKeys.language.tr(),
isForLanguage: true,
onTap: () {
if (EasyLocalization.of(context)
?.currentLocale
?.countryCode ==
"SA") {
context.setLocale(const Locale("en", "US"));
} else {
context.setLocale(const Locale('ar', 'SA'));
}
// if (EasyLocalization.of(context)
// ?.currentLocale
// ?.countryCode ==
// "SA") {
// context.setLocale(const Locale("en", "US"));
// } else {
// context.setLocale(const Locale('ar', 'SA'));
// }
context.read<UserVM>().changeLanguage(context);
},
).toWhiteContainer(
width: double.infinity,
pading: const EdgeInsets.all(12),
borderRadius: 0),
).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0),
10.height,
(AppState().currentAppType == AppType.provider)
? Column(
@ -109,13 +103,12 @@ class SettingOptionsLanguage extends StatelessWidget {
color: MyColors.primaryColor,
),
),
titleText: LocaleKeys.mySubscriptions.tr(),
subTitle: "Silver",
titleText: LocaleKeys.mySubscription.tr(),
subTitle: AppState().getproviderSubscription.first.subscriptionName ?? "Silver",
isForLanguage: false,
needBorderBelow: true,
onTap: () {
navigateWithName(
context, AppRoutes.mySubscriptionsPage);
navigateWithName(context, AppRoutes.mySubscriptionsPage);
},
),
CustomSettingOptionsTile(
@ -132,8 +125,7 @@ class SettingOptionsLanguage extends StatelessWidget {
isForLanguage: false,
needBorderBelow: true,
onTap: () {
navigateWithName(
context, AppRoutes.subscriptionsPage);
navigateWithName(context, AppRoutes.subscriptionsPage);
},
),
CustomSettingOptionsTile(
@ -150,19 +142,13 @@ class SettingOptionsLanguage extends StatelessWidget {
isForLanguage: false,
needBorderBelow: false,
onTap: () {
navigateWithName(
context, AppRoutes.providerLicensePage);
navigateWithName(context, AppRoutes.providerLicensePage);
},
)
],
).toWhiteContainer(
width: double.infinity,
pading: const EdgeInsets.all(12),
borderRadius: 0)
: SizedBox(),
(AppState().currentAppType == AppType.provider)
? 10.height
).toWhiteContainer(width: double.infinity, pading: const EdgeInsets.all(12), borderRadius: 0)
: SizedBox(),
(AppState().currentAppType == AppType.provider) ? 10.height : SizedBox(),
],
)),
// : Expanded(
@ -188,9 +174,7 @@ class SettingOptionsLanguage extends StatelessWidget {
// ],
// ),
// ),
(AppState().currentAppType == AppType.provider)
? Text(LocaleKeys.provider.tr())
: Text(LocaleKeys.customer.tr()),
(AppState().currentAppType == AppType.provider) ? Text(LocaleKeys.provider.tr()) : Text(LocaleKeys.customer.tr()),
Row(
children: [
Expanded(
@ -201,7 +185,9 @@ class SettingOptionsLanguage extends StatelessWidget {
fontSize: 16,
maxHeight: 55,
title: LocaleKeys.logOut.tr(),
onPressed: () {},
onPressed: () {
context.read<UserVM>().logout(context);
},
),
),
],

@ -46,13 +46,14 @@ class _LoginWithPasswordState extends State<LoginWithPassword> {
void initState() {
super.initState();
scheduleMicrotask(() {
if (AppState().currentAppType == AppType.provider) {
phoneNum = "966530896018";
password = "Amir@1234";
}
userVM = Provider.of(context, listen: false);
context.read<UserVM>().getAvailBio();
if (AppState().currentAppType == AppType.provider) {
// phoneNum = "966530896018";
// password = "Amir@1234";
phoneNum = "966569755630";
password = "Amir12345@";
}
getCountryList();
});

@ -42,6 +42,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
@override
Widget build(BuildContext context) {
// print("User Image URL == ${AppState().getUser.data!.userInfo!.userImageUrl} ============");
return Column(
children: [
AppBar(
@ -64,27 +65,24 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget {
).toCircle(borderRadius: 100)
: profileImageUrl.isEmpty && AppState().getUser.data!.userInfo!.userImageUrl != null
? CachedNetworkImage(
imageUrl: AppState().getUser.data!.userInfo!.userImageUrl,
imageBuilder: (context, imageProvider) =>
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: imageProvider,
fit: BoxFit.cover,
imageUrl: AppState().getUser.data!.userInfo!.userImageUrl,
imageBuilder: (context, imageProvider) =>
Container(
decoration: BoxDecoration(
image: DecorationImage(
image: imageProvider,
fit: BoxFit.cover,
),
),
),
),
placeholder: (context, url) => const Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => const Icon(Icons.error),
fadeInCurve: Curves.easeIn,
width: 34,
height: 34,
fit: BoxFit.fill,
fadeInDuration: Duration(milliseconds: 1000),
useOldImageOnUrlChange: false,
placeholder: (context, url) => const Center(child: CircularProgressIndicator()),
errorWidget: (context, url, error) => const Icon(Icons.supervised_user_circle_outlined),
fadeInCurve: Curves.easeIn,
width: 34,
height: 34,
fit: BoxFit.fill,
fadeInDuration: Duration(milliseconds: 1000),
useOldImageOnUrlChange: false
).toCircle(borderRadius: 100)
: Image.asset(
MyAssets.carBanner,

@ -3,19 +3,13 @@ import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
class MenuTabs extends StatefulWidget {
int selectedIndex;
class MenuTabs extends StatelessWidget {
List<DropValue> dropList;
Function(DropValue value) onSelect;
Function(DropValue value, int index ) onSelected;
Color? selectedColor;
MenuTabs(this.selectedIndex, this.dropList, {required this.onSelect, this.selectedColor});
MenuTabs(this.dropList, {required this.onSelected, this.selectedColor});
@override
State<MenuTabs> createState() => _RoleTypeTabState();
}
class _RoleTypeTabState extends State<MenuTabs> {
@override
Widget build(BuildContext context) {
return SizedBox(
@ -25,24 +19,21 @@ class _RoleTypeTabState extends State<MenuTabs> {
itemBuilder: (context, index) {
return InkWell(
onTap: () {
setState(() {
widget.selectedIndex = index;
widget.onSelect(widget.dropList[index]);
});
onSelected(dropList[index], index);
},
child: Container(
height: 45,
decoration: BoxDecoration(
color: widget.selectedIndex == index ? widget.selectedColor ?? MyColors.darkIconColor : Colors.white,
border: Border.all(color: widget.selectedIndex == index ? widget.selectedColor ?? MyColors.darkIconColor : MyColors.darkPrimaryColor, width: 1.5),
color: dropList[index].isEnabled! ? selectedColor ?? MyColors.darkIconColor : Colors.white,
border: Border.all(color: dropList[index].isEnabled! ? selectedColor ?? MyColors.darkIconColor : MyColors.darkPrimaryColor, width: 1.5),
borderRadius: const BorderRadius.all(Radius.circular(0)),
),
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Center(
child: Text(
widget.dropList[index].value,
dropList[index].value,
style: TextStyle(
color: widget.selectedIndex == index ? MyColors.white : Colors.black,
color: dropList[index].isEnabled! ? MyColors.white : Colors.black,
fontSize: 12,
fontWeight: FontWeight.w600,
),
@ -55,7 +46,7 @@ class _RoleTypeTabState extends State<MenuTabs> {
return 12.width;
},
padding: const EdgeInsets.symmetric(horizontal: 21),
itemCount: widget.dropList.length,
itemCount: dropList.length,
scrollDirection: Axis.horizontal,
),
);

@ -20,7 +20,7 @@ class _RoleTypeTabState extends State<RoleTypeTab> {
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
height: 45,
height: 50,
child: ListView.separated(
itemBuilder: (context, index) {
return InkWell(
@ -32,7 +32,7 @@ class _RoleTypeTabState extends State<RoleTypeTab> {
},
child: Container(
width: widget.width ?? (MediaQuery.of(context).size.width / 2) - 30,
height: 45,
height: 50,
decoration: BoxDecoration(
color: widget.selectedIndex == index ? MyColors.darkPrimaryColor : Colors.grey[200],
// border: Border.all(color: type == ClassType.NUMBER ? MyColors.darkPrimaryColor : Colors.transparent, width: 2),
@ -43,13 +43,16 @@ class _RoleTypeTabState extends State<RoleTypeTab> {
child: Center(
child: Text(
(widget.dropList[index].value) == "ServiceProvider_Dealership" || (widget.dropList[index].value) == "ServiceProvider_Individual"
? widget.dropList[index].value.split("_").first + "\n" + widget.dropList[index].value.split("_").last
? "${widget.dropList[index].value.split("_").first}\n${widget.dropList[index].value.split("_").last}"
: widget.dropList[index].value,
textAlign: TextAlign.center,
style: TextStyle(
color: widget.selectedIndex == index ? MyColors.white : Colors.black,
fontSize: 15,
height: 1
),
),
),
),

@ -47,7 +47,7 @@ dependencies:
google_maps_flutter: ^2.1.1
geolocator: any
# geocoding: ^2.1.0
geocoding: ^2.1.1
geocoding: ^3.0.0
# Auth
@ -73,10 +73,15 @@ flutter:
- assets/icons/
- assets/icons/payments/
- assets/images/
- assets/fonts/Poppins-Medium.ttf
- assets/fonts/
fonts:
- family: Poppins
fonts:
- asset: assets/fonts/Poppins-Medium.ttf
- family: GessTwo
fonts:
- asset: assets/fonts/GESS-Two-Light.otf
- asset: assets/fonts/GESS-Two-Bold.otf
- asset: assets/fonts/GESS-Two-Medium.otf

Loading…
Cancel
Save