diff --git a/android/build.gradle b/android/build.gradle
index 543cb25..aca8b4a 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -6,7 +6,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:4.1.0'
+ classpath 'com.android.tools.build:gradle:7.4.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index e547954..53d5a7c 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 8d4492f..9625e10 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 9.0
+ 11.0
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 899dfbb..d193b7b 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -68,7 +68,6 @@
C74C73D850C4D4FC94940060 /* Pods-Runner.release.xcconfig */,
3643750A79F4A25346F39B6F /* Pods-Runner.profile.xcconfig */,
);
- name = Pods;
path = Pods;
sourceTree = "";
};
@@ -140,6 +139,7 @@
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
9A2045E27F192C87BCD2FA50 /* [CP] Embed Pods Frameworks */,
+ 4CC2E88FCFA89EAD7EEA637B /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -156,7 +156,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1020;
+ LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -200,10 +200,12 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
+ "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@@ -212,8 +214,26 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
+ 4CC2E88FCFA89EAD7EEA637B /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Copy Pods Resources";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -340,7 +360,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -356,9 +376,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 99Z3UD3LJM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.example.carCustomerApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -414,7 +439,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -463,11 +488,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
- SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
@@ -480,9 +506,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 99Z3UD3LJM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.example.carCustomerApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -499,9 +530,14 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ DEVELOPMENT_TEAM = 99Z3UD3LJM;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
PRODUCT_BUNDLE_IDENTIFIER = com.example.carCustomerApp;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index a28140c..3db53b6 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
+ NSCameraUsageDescription
+ Used to access media images for car parts
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleExecutable
@@ -28,18 +30,22 @@
Main
UISupportedInterfaceOrientations
- UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
+ UIInterfaceOrientationPortrait
UISupportedInterfaceOrientations~ipad
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
UIViewControllerBasedStatusBarAppearance
+ CADisableMinimumFrameDurationOnPhone
+
+ UIApplicationSupportsIndirectInputEvents
+
diff --git a/lib/config/customer_dependencies.dart b/lib/config/customer_dependencies.dart
index 3debdff..804a53f 100644
--- a/lib/config/customer_dependencies.dart
+++ b/lib/config/customer_dependencies.dart
@@ -1,10 +1,12 @@
import 'package:car_customer_app/repositories/provider_repo.dart';
+import 'package:car_customer_app/repositories/schedule_repo.dart';
import 'package:mc_common_app/config/dependencies.dart';
class CustomerDependencies {
static void addDependencies() {
AppDependencies.addDependencies();
injector.registerSingleton(() => ProviderRepoImp());
+ injector.registerSingleton(() => ScheduleRepoImp());
}
}
diff --git a/lib/config/customer_routes.dart b/lib/config/customer_routes.dart
index f68dfef..6cca179 100644
--- a/lib/config/customer_routes.dart
+++ b/lib/config/customer_routes.dart
@@ -1,6 +1,8 @@
import 'package:car_customer_app/views/appointments/appointment_detail_view.dart';
import 'package:car_customer_app/views/appointments/book_appointment_services_view.dart';
+import 'package:car_customer_app/views/appointments/book_appointments_item_view.dart';
import 'package:car_customer_app/views/appointments/pick_items_view.dart';
+import 'package:car_customer_app/views/appointments/review_appointment_view.dart';
import 'package:car_customer_app/views/dashboard/dashboard_page.dart';
import 'package:car_customer_app/views/provider/branch_detail_page.dart';
import 'package:car_customer_app/views/provider/provider_profile_page.dart';
@@ -8,21 +10,28 @@ import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
-import 'package:mc_common_app/models/services/branch_model.dart';
+import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
+import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/views/advertisement/ads_detail_view.dart';
import 'package:mc_common_app/views/advertisement/create_ad_view.dart';
+import 'package:mc_common_app/views/advertisement/select_ad_type_view.dart';
import 'package:mc_common_app/views/payments/payment_methods_view.dart';
+import 'package:mc_common_app/views/advertisement/ads_search_filter_view.dart';
-class CustomerAppRoutes {
+ class CustomerAppRoutes {
static final Map routes = {
AppRoutes.dashboard: (context) => DashboardPage(),
AppRoutes.bookProviderAppView: (context) => BookProviderAppView(),
AppRoutes.appointmentDetailView: (context) => AppointmentDetailView(appointmentListModel: ModalRoute.of(context)!.settings.arguments as AppointmentListModel),
AppRoutes.adsDetailView: (context) => AdsDetailView(adDetails: ModalRoute.of(context)!.settings.arguments as AdDetailsModel),
AppRoutes.createAdView: (context) => CreateAdView(),
+ AppRoutes.adsSearchFilterScreen: (context) => AdsSearchFilterView(),
+ AppRoutes.selectAdTypeView: (context) => SelectAdTypeView(isProvider: ModalRoute.of(context)!.settings.arguments as bool),
AppRoutes.bookAppointmenServicesView: (context) => BookAppointmentServicesView(),
- AppRoutes.paymentMethodsView: (context) => PaymentMethodsView(),
- AppRoutes.branchDetailPage: (context) => BranchDetailPage(branchModel: ModalRoute.of(context)!.settings.arguments as BranchModel),
+ AppRoutes.bookAppointmentsItemView: (context) => BookAppointmentsItemView(),
+ AppRoutes.reviewAppointmentView: (context) => ReviewAppointment(),
+ AppRoutes.paymentMethodsView: (context) => PaymentMethodsView(paymentType: ModalRoute.of(context)!.settings.arguments as PaymentTypesEnum),
+ AppRoutes.branchDetailPage: (context) => BranchDetailPage(branchDetailModel: ModalRoute.of(context)!.settings.arguments as BranchDetailModel),
AppRoutes.providerProfilePage: (context) => ProviderProfilePage(providerId: ModalRoute.of(context)!.settings.arguments as int),
};
}
diff --git a/lib/main.dart b/lib/main.dart
index e053104..966f089 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,9 +1,9 @@
import 'package:car_customer_app/config/customer_dependencies.dart';
import 'package:car_customer_app/config/customer_routes.dart';
import 'package:car_customer_app/repositories/provider_repo.dart';
+import 'package:car_customer_app/repositories/schedule_repo.dart';
import 'package:car_customer_app/view_models/appointments_view_model.dart';
import 'package:car_customer_app/view_models/dashboard_view_model.dart';
-import 'package:car_customer_app/view_models/providers_view_model.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
@@ -27,6 +27,7 @@ import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';
import 'package:sizer/sizer.dart';
+//test commit
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
CustomerDependencies.addDependencies();
@@ -53,15 +54,10 @@ Future main() async {
adsRepo: injector.get(),
),
),
- ChangeNotifierProvider(
- create: (_) => ProvidersVM(
- commonServices: injector.get(),
- commonRepo: injector.get(),
- providerRepo: injector.get(),
- ),
- ),
ChangeNotifierProvider(
create: (_) => AppointmentsVM(
+ scheduleRepo: injector.get(),
+ providerRepo: injector.get(),
commonServices: injector.get(),
commonRepo: injector.get(),
),
diff --git a/lib/repositories/provider_repo.dart b/lib/repositories/provider_repo.dart
index d92a66d..fee2cc1 100644
--- a/lib/repositories/provider_repo.dart
+++ b/lib/repositories/provider_repo.dart
@@ -1,51 +1,55 @@
import 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-import 'package:mc_common_app/models/model/provider_model.dart';
-import 'package:mc_common_app/models/services/item_model.dart';
-import 'package:mc_common_app/models/services/near_branch_model.dart';
-import 'package:http/http.dart' as http;
import 'package:mc_common_app/api/api_client.dart';
import 'package:mc_common_app/classes/app_state.dart';
-
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependencies.dart';
-
-import 'package:flutter/cupertino.dart';
+import 'package:mc_common_app/models/generic_resp_model.dart';
+import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
+import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart';
+import 'package:mc_common_app/models/services/item_model.dart';
abstract class ProviderRepo {
- Future getAllNearBranchAndServices();
+ Future> getAllNearBranchAndServices();
- Future getServiceItems(int serviceId);
+ Future> getServiceItems(int serviceId);
- Future getBranchAndServices(int providerId);
+ Future getBranchAndServices(int providerId);
}
class ProviderRepoImp implements ProviderRepo {
+ ApiClient apiClient = injector.get();
+ AppState appState = injector.get();
+
@override
- Future getAllNearBranchAndServices() async {
- // var postParams = {"serviceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""};
- String t = AppState().getUser.data!.accessToken ?? "";
- return await injector.get().getJsonForObject((json) => NearBrancheModel.fromJson(json), ApiConsts.GetAllNearBranches, token: t);
+ Future> getAllNearBranchAndServices() async {
+ GenericRespModel adsGenericModel = await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.GetAllNearBranches, token: appState.getUser.data!.accessToken);
+ List nearBranches = List.generate(adsGenericModel.data.length, (index) => BranchDetailModel.fromJson(adsGenericModel.data[index]));
+ return nearBranches;
}
@override
- Future getServiceItems(int serviceId) async {
+ Future> getServiceItems(int serviceId) async {
var queryParameters = {
"ServiceProviderServiceID": serviceId.toString(),
};
- String? token = AppState().getUser.data?.accessToken;
- debugPrint(token);
- return await injector
- .get()
- .getJsonForObject((json) => ItemModel.fromJson(json), ApiConsts.getServiceItems, queryParameters: queryParameters, token: AppState().getUser.data!.accessToken ?? "");
+
+ GenericRespModel adsGenericModel = await apiClient.getJsonForObject(
+ (json) => GenericRespModel.fromJson(json),
+ ApiConsts.getServiceItems,
+ token: appState.getUser.data!.accessToken,
+ queryParameters: queryParameters,
+ );
+ List serviceItems = List.generate(adsGenericModel.data.length, (index) => ItemData.fromJson(adsGenericModel.data[index]));
+ return serviceItems;
}
@override
- Future getBranchAndServices(int providerId) async {
+ Future getBranchAndServices(int providerId) async {
var postParams = {"serviceProviderID": providerId.toString()};
- String t = AppState().getUser.data!.accessToken ?? "";
- return await injector.get().getJsonForObject((json) => ProviderModel.fromJson(json), ApiConsts.BranchesAndServices, queryParameters: postParams, token: t);
+ GenericRespModel adsGenericModel =
+ await apiClient.getJsonForObject((json) => GenericRespModel.fromJson(json), ApiConsts.BranchesAndServices, token: appState.getUser.data!.accessToken, queryParameters: postParams);
+
+ return ProviderProfileModel.fromJson(adsGenericModel.data);
}
}
diff --git a/lib/repositories/schedule_repo.dart b/lib/repositories/schedule_repo.dart
new file mode 100644
index 0000000..7938095
--- /dev/null
+++ b/lib/repositories/schedule_repo.dart
@@ -0,0 +1,88 @@
+import 'package:mc_common_app/api/api_client.dart';
+import 'package:mc_common_app/classes/app_state.dart';
+import 'package:mc_common_app/classes/consts.dart';
+import 'package:mc_common_app/config/dependencies.dart';
+import 'package:mc_common_app/models/generic_resp_model.dart';
+import 'package:mc_common_app/models/m_response.dart';
+import 'package:mc_common_app/models/provider_branches_models/profile/services.dart';
+import 'package:mc_common_app/models/schedule_model.dart';
+import 'package:mc_common_app/models/service_schedule_model.dart';
+
+abstract class ScheduleRepo {
+ Future getAllServices(String branchId);
+
+ Future createSchedule(Map map);
+
+ Future addServicesInSchedule(Map map);
+
+ Future updateSchedule(Map map);
+
+ Future> getSchedules(String branchId);
+
+ Future updateServicesInSchedule(Map map);
+
+ Future> mergeServiceIntoAvailableSchedules({required List serviceItemIds});
+}
+
+class ScheduleRepoImp implements ScheduleRepo {
+ @override
+ Future getAllServices(String branchId) async {
+ Map map = {"ProviderBranchID": branchId};
+ String t = AppState().getUser.data!.accessToken ?? "";
+ return await injector.get().getJsonForObject((json) => Services.fromJson(json), ApiConsts.getServicesOfBranch, token: t, queryParameters: map);
+ }
+
+ @override
+ Future createSchedule(Map map) async {
+ String t = AppState().getUser.data!.accessToken ?? "";
+ return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createSchedule, map, token: t);
+ }
+
+ @override
+ Future addServicesInSchedule(Map map) async {
+ String t = AppState().getUser.data!.accessToken ?? "";
+ return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createGroup, map, token: t);
+ }
+
+ @override
+ Future> getSchedules(String branchId) async {
+ Map map = {"ServiceProviderBranchID": branchId};
+ String t = AppState().getUser.data!.accessToken ?? "";
+
+ GenericRespModel adsGenericModel = await injector.get().getJsonForObject(
+ (json) => GenericRespModel.fromJson(json),
+ ApiConsts.getSchedule,
+ token: t,
+ queryParameters: map,
+ );
+
+ return List.generate(adsGenericModel.data.length, (index) => ScheduleData.fromJson(adsGenericModel.data[index]));
+ }
+
+ @override
+ Future updateSchedule(Map map) async {
+ String t = AppState().getUser.data!.accessToken ?? "";
+ return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateSchedule, map, token: t);
+ }
+
+ @override
+ Future updateServicesInSchedule(Map map) async {
+ String t = AppState().getUser.data!.accessToken ?? "";
+ return await injector.get().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateGroup, map, token: t);
+ }
+
+ Future> mergeServiceIntoAvailableSchedules({required List serviceItemIds}) async {
+ String t = AppState().getUser.data!.accessToken ?? "";
+ var dummyServiceIds = ["3", "2"];
+ var queryParameters = {"ServiceItemIDs": dummyServiceIds};
+ GenericRespModel adsGenericModel = await injector.get().getJsonForObject(
+ (json) => GenericRespModel.fromJson(json),
+ ApiConsts.GetServiceItemAppointmentScheduleSlots,
+ token: t,
+ queryParameters: queryParameters,
+ );
+ List serviceAppointmentScheduleModel =
+ List.generate(adsGenericModel.data.length, (index) => ServiceAppointmentScheduleModel.fromJson(adsGenericModel.data[index]));
+ return serviceAppointmentScheduleModel;
+ }
+}
diff --git a/lib/view_models/appointments_view_model.dart b/lib/view_models/appointments_view_model.dart
index 2fb9aa2..08889a9 100644
--- a/lib/view_models/appointments_view_model.dart
+++ b/lib/view_models/appointments_view_model.dart
@@ -1,28 +1,78 @@
-import 'package:flutter/cupertino.dart';
+import 'package:car_customer_app/repositories/provider_repo.dart';
+import 'package:car_customer_app/repositories/schedule_repo.dart';
+import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
-import 'package:mc_common_app/models/provider_category_model.dart';
-import 'package:mc_common_app/models/provider_service_model.dart';
+import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
+import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart';
+import 'package:mc_common_app/models/service_schedule_model.dart';
+import 'package:mc_common_app/models/services/item_model.dart';
+import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/widgets_models.dart';
import 'package:mc_common_app/repositories/common_repo.dart';
import 'package:mc_common_app/services/common_services.dart';
+import 'package:mc_common_app/utils/enums.dart';
+import 'package:mc_common_app/view_models/base_view_model.dart';
+import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
-class AppointmentsVM extends ChangeNotifier {
+class AppointmentsVM extends BaseVM {
final CommonRepo commonRepo;
final CommonAppServices commonServices;
+ final ProviderRepo providerRepo;
+ final ScheduleRepo scheduleRepo;
- AppointmentsVM({required this.commonServices, required this.commonRepo});
+ AppointmentsVM({required this.commonServices, required this.scheduleRepo, required this.providerRepo, required this.commonRepo});
bool isFetchingLists = false;
List myAppointments = [];
List appointmentsFilterOptions = [];
+ // List availableSchedules = [];
+
bool isFetchingServices = false;
- List providerCategories = [];
+ List branchCategories = [];
bool isHomeTapped = false;
+ List serviceAppointmentScheduleList = [];
+
+ // Future getSchedulesByBranchId() async {
+ // availableSchedules = await scheduleRepo.getSchedules(selectedBranchModel!.id!.toString());
+ // log("schedules: ${availableSchedules.toString()}");
+ // notifyListeners();
+ // }
+
+ List servicesInSchedule = [];
+
+ Future mergeServiceIntoAvailableSchedules() async {
+ List serviceItemIds = [];
+ serviceItems.forEach((serviceItem) {
+ if (serviceItem.isUpdateOrSelected!) {
+ serviceItemIds.add(serviceItem.id!.toString());
+ }
+ });
+ var scheduleList = await scheduleRepo.mergeServiceIntoAvailableSchedules(serviceItemIds: serviceItemIds);
+ serviceAppointmentScheduleList.addAll(scheduleList);
+ servicesInSchedule.clear();
+ serviceAppointmentScheduleList.forEach((schedule) {
+ schedule.serviceItemList!.forEach((item) {
+ if (!ifItemAlreadyThere(item.serviceProviderServiceId!)) {
+ servicesInSchedule.add(DropValue(item.serviceProviderServiceId!, item.description!, ""));
+ }
+ });
+ });
+ notifyListeners();
+ }
+
+ bool ifItemAlreadyThere(int id) {
+ int index = servicesInSchedule.indexWhere((element) => element.id == id);
+ if (index == -1) {
+ return false;
+ }
+ return true;
+ }
+
void updateIsHomeTapped(bool value) {
isHomeTapped = value;
notifyListeners();
@@ -32,44 +82,38 @@ class AppointmentsVM extends ChangeNotifier {
void updatePickedHomeLocation(String value) {
pickedHomeLocation = value;
+ pickHomeLocationError = "";
notifyListeners();
}
- SelectionModel providerCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
+ SelectionModel branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
- void updateProviderCategoryId(SelectionModel id) async {
- providerCategoryId = id;
- await getProviderServices(id.selectedId);
+ void updateProviderCategoryId(SelectionModel id) {
+ branchSelectedCategoryId = id;
+ getBranchServices(categoryId: branchSelectedCategoryId.selectedId);
notifyListeners();
}
- List providerServices = [];
+ List providersFilterOptions = [];
+ List nearbyBranches = [];
+ BranchDetailModel? selectedBranchModel;
- SelectionModel providerServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
+ List branchServices = [];
+ ServiceModel? currentServiceSelection;
- void updateProviderServiceId(SelectionModel id) async {
- providerServiceId = id;
- notifyListeners();
- }
+ void updateBranchServiceId(SelectionModel id) async {
+ branchSelectedServiceId = id;
+ currentServiceSelection = branchServices.firstWhere((element) => element.serviceProviderServiceId == id.selectedId);
- void getProviderCategories() async {
- notifyListeners();
- providerCategories = await commonRepo.getProviderServiceCategories();
notifyListeners();
}
- getProviderServices(int categoryId) async {
- providerServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
+ resetCategorySelectionBottomSheet() {
+ selectedSubServicesCounter = 0;
+ branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
isHomeTapped = false;
- pickedHomeLocation = "";
- if (categoryId != -1) {
- isFetchingServices = true;
- notifyListeners();
- providerServices = await commonRepo.getProviderServices(categoryId: categoryId);
- isFetchingServices = false;
-
- notifyListeners();
- }
+ branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
+ currentServiceSelection = null;
}
populateAppointmentsFilterList() {
@@ -99,4 +143,174 @@ class AppointmentsVM extends ChangeNotifier {
isFetchingLists = false;
notifyListeners();
}
+
+ updateSelectedBranch(BranchDetailModel branchDetailModel) {
+ selectedBranchModel = branchDetailModel;
+ getBranchCategories();
+ notifyListeners();
+ }
+
+ List serviceItems = [];
+ List selectedServiceItems = [];
+ ProviderProfileModel? providerProfileModel;
+
+ int selectedSubServicesCounter = 0;
+
+ updateSelectedSubServicesCounter(int value) {
+ selectedSubServicesCounter = value;
+ notifyListeners();
+ }
+
+ onItemUpdateOrSelected(int index, bool selected, int itemId) {
+ serviceItems[index].isUpdateOrSelected = selected;
+ if (selected) {
+ selectedSubServicesCounter = selectedSubServicesCounter + 1;
+ updateSelectedSubServicesCounter(selectedSubServicesCounter);
+ selectSubServicesError = "";
+ currentServiceSelection!.serviceItems!.add(serviceItems[index]);
+ }
+ if (!selected) {
+ selectedSubServicesCounter = selectedSubServicesCounter - 1;
+ updateSelectedSubServicesCounter(selectedSubServicesCounter);
+ currentServiceSelection!.serviceItems!.removeWhere((element) => element.id == itemId);
+ }
+ notifyListeners();
+ }
+
+ populateProvidersFilterList() {
+ providersFilterOptions.clear();
+ providersFilterOptions = [
+ FilterListModel(title: "All Providers", isSelected: true, id: -1),
+ FilterListModel(title: "Maintenance", isSelected: false, id: 0),
+ FilterListModel(title: "Oil Service", isSelected: false, id: 1),
+ FilterListModel(title: "Accessories", isSelected: false, id: 2),
+ FilterListModel(title: "Tire Service", isSelected: false, id: 3),
+ FilterListModel(title: "Dent and Paint", isSelected: false, id: 4),
+ ];
+ notifyListeners();
+ }
+
+ applyFilterOnProviders({required int index}) {
+ if (providersFilterOptions.isEmpty) return;
+ for (var value in providersFilterOptions) {
+ value.isSelected = false;
+ }
+ providersFilterOptions[index].isSelected = true;
+ notifyListeners();
+ }
+
+ getAllNearBranches({bool isNeedToRebuild = false}) async {
+ //TODO: needs to lat,long into API
+ nearbyBranches.clear();
+ if (isNeedToRebuild) setState(ViewState.busy);
+ nearbyBranches = await providerRepo.getAllNearBranchAndServices();
+ setState(ViewState.idle);
+ }
+
+ Future> getServiceItems(int serviceId) async {
+ serviceItems.clear();
+ serviceItems = await providerRepo.getServiceItems(serviceId);
+ setState(ViewState.idle);
+ return serviceItems;
+ }
+
+ getBranchAndServices(int providerId) async {
+ providerProfileModel = null;
+ providerProfileModel = await providerRepo.getBranchAndServices(providerId);
+ setState(ViewState.idle);
+ }
+
+ String pickHomeLocationError = "";
+ String selectSubServicesError = "";
+
+ SelectionModel branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
+
+ bool isCategoryAlreadyPresent(int id) {
+ final contain = branchCategories.where((element) => element.id == id);
+ if (contain.isEmpty) {
+ return false;
+ }
+ return true;
+ }
+
+ void getBranchCategories() async {
+ for (var value in selectedBranchModel!.branchServices!) {
+ if (!isCategoryAlreadyPresent(value.categoryId!)) {
+ branchCategories.add(DropValue(value.categoryId!, value.categoryName!, ""));
+ }
+ }
+ notifyListeners();
+ }
+
+ getBranchServices({required int categoryId}) async {
+ branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
+ isHomeTapped = false;
+ pickedHomeLocation = "";
+ pickHomeLocationError = "";
+ if (categoryId != -1) {
+ isFetchingServices = true;
+ // notifyListeners();
+ branchServices = getFilteredBranchServices(categoryId: categoryId);
+ isFetchingServices = false;
+ notifyListeners();
+ }
+ }
+
+ List getFilteredBranchServices({required int categoryId}) {
+ List filteredServices = selectedBranchModel!.branchServices!.where((element) => element.categoryId == categoryId).toList();
+ return filteredServices;
+ }
+
+ void updatePickHomeLocationError(String value) {
+ pickHomeLocationError = value;
+ notifyListeners();
+ }
+
+ bool isServiceSelectionValidated() {
+ if (branchSelectedServiceId.selectedId == -1) {
+ return false;
+ }
+
+ if (isHomeTapped) {
+ if (pickedHomeLocation == "") {
+ updatePickHomeLocationError(GlobalConsts.homeLocationEmptyError);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool onSubServicesNextPressed() {
+ for (var value in serviceItems) {
+ if (value.isUpdateOrSelected!) {
+ return true;
+ }
+ }
+ selectSubServicesError = "Please select at least one sub service";
+ notifyListeners();
+ return false;
+ }
+
+// void mergeServiceInAvailableSchedule() {
+// log("schedules: ${availableSchedules}");
+// for (var schedule in availableSchedules) {
+// for (var service in schedule.scheduleServices!) {
+// if (branchSelectedServiceId.selectedId == service.serviceId) {
+// log("ID matched: ${service.serviceId}");
+// log("SelectedServices: ${schedule.selectedServices}");
+//
+//
+// int isAlreadyThereIndex = schedule.selectedServices!.indexWhere((element) => element.serviceProviderServiceId == branchSelectedServiceId.selectedId);
+// if (isAlreadyThereIndex != -1) {
+// log("removing: ${service.serviceId}");
+// schedule.selectedServices!.removeAt(isAlreadyThereIndex);
+// }
+// schedule.selectedServices!.add(currentServiceSelection!);
+// notifyListeners();
+// return;
+// }
+// }
+// }
+// notifyListeners();
+// }
}
diff --git a/lib/view_models/providers_view_model.dart b/lib/view_models/providers_view_model.dart
deleted file mode 100644
index 568f713..0000000
--- a/lib/view_models/providers_view_model.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-import 'package:mc_common_app/models/model/provider_model.dart';
-import 'package:mc_common_app/models/services/item_model.dart';
-import 'package:mc_common_app/models/services/near_branch_model.dart';
-import 'package:car_customer_app/repositories/provider_repo.dart';
-import 'package:flutter/cupertino.dart';
-import 'package:mc_common_app/models/widgets_models.dart';
-import 'package:mc_common_app/repositories/common_repo.dart';
-import 'package:mc_common_app/services/common_services.dart';
-import 'package:mc_common_app/utils/enums.dart';
-import 'package:mc_common_app/view_models/base_view_model.dart';
-
-class ProvidersVM extends BaseVM {
- final CommonRepo commonRepo;
- final CommonAppServices commonServices;
- final ProviderRepo providerRepo;
-
- ProvidersVM({required this.commonServices, required this.commonRepo, required this.providerRepo});
-
- List providersFilterOptions = [];
- NearBrancheModel? branches;
- ItemModel? serviceItems;
- ProviderModel? providerModel;
-
- populateProvidersFilterList() {
- providersFilterOptions.clear();
- providersFilterOptions = [
- FilterListModel(title: "All Providers", isSelected: true, id: -1),
- FilterListModel(title: "Maintenance", isSelected: false, id: 0),
- FilterListModel(title: "Oil Service", isSelected: false, id: 1),
- FilterListModel(title: "Accessories", isSelected: false, id: 2),
- FilterListModel(title: "Tire Service", isSelected: false, id: 3),
- FilterListModel(title: "Dent and Paint", isSelected: false, id: 4),
- ];
- notifyListeners();
- }
-
- applyFilterOnProviders({required int index}) {
- if (providersFilterOptions.isEmpty) return;
- for (var value in providersFilterOptions) {
- value.isSelected = false;
- }
- providersFilterOptions[index].isSelected = true;
- notifyListeners();
- }
-
- //Create new branch
- getAllNearBranches({bool isNeedToRebuild = false}) async {
- //TODO: needs to lat,long into API
- branches = null;
- if (isNeedToRebuild) setState(ViewState.busy);
- branches = await providerRepo.getAllNearBranchAndServices();
- setState(ViewState.idle);
- }
-
- Future getServiceItems(int serviceId) async {
- serviceItems = null;
- serviceItems = await providerRepo.getServiceItems(serviceId);
- setState(ViewState.idle);
- return serviceItems;
- }
-
- getBranchAndServices(int providerId) async {
- providerModel = null;
- providerModel = await providerRepo.getBranchAndServices(providerId);
- setState(ViewState.idle);
- }
-}
diff --git a/lib/views/appointments/book_appointment_services_view.dart b/lib/views/appointments/book_appointment_services_view.dart
index 71f4bb3..2212426 100644
--- a/lib/views/appointments/book_appointment_services_view.dart
+++ b/lib/views/appointments/book_appointment_services_view.dart
@@ -1,195 +1,133 @@
import 'package:car_customer_app/view_models/appointments_view_model.dart';
+import 'package:car_customer_app/views/appointments/widgets/appointment_service_pick_bottom_sheet.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';
+import 'package:mc_common_app/models/service_schedule_model.dart';
+import 'package:mc_common_app/models/services/item_model.dart';
import 'package:mc_common_app/models/widgets_models.dart';
import 'package:mc_common_app/theme/colors.dart';
+import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/views/advertisement/custom_add_button.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/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:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
class BookAppointmentServicesView extends StatelessWidget {
- const BookAppointmentServicesView({Key? key}) : super(key: key);
+ BookAppointmentServicesView({Key? key}) : super(key: key);
- void openTheAddServiceBottomSheet(BuildContext context) {
+ void openTheAddServiceBottomSheet(BuildContext context, AppointmentsVM appointmentsVM) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
builder: (BuildContext context) {
- AppointmentsVM appointmentsVM = context.watch();
- return SizedBox(
- height: MediaQuery.of(context).size.height * 0.85,
- child: Column(
- children: [
- Container(
- margin: const EdgeInsets.all(8),
- height: 8,
- width: 60,
- decoration: const BoxDecoration(color: MyColors.lightTextColor, borderRadius: BorderRadius.all(Radius.circular(20))),
- ),
- 12.height,
- Row(
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- "Select Category".toText(fontSize: 24, isBold: true),
- ],
- ),
- 30.height,
- Expanded(
- child: ListView(
- children: [
- Builder(
- builder: (context) {
- List serviceCategories = [];
- for (var element in appointmentsVM.providerCategories) {
- if (!element.isSelected!) {
- serviceCategories.add(DropValue(element.id?.toInt() ?? 0, element.categoryName ?? "", ""));
- }
- }
- return DropdownField(
- (DropValue value) => appointmentsVM.updateProviderCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)),
- list: serviceCategories,
- hint: "Select Category",
- dropdownValue: appointmentsVM.providerCategoryId.selectedId != -1
- ? DropValue(appointmentsVM.providerCategoryId.selectedId, appointmentsVM.providerCategoryId.selectedOption, "")
- : null,
- );
- },
+ return AppointmentServicePickBottomSheet();
+ },
+ );
+ }
+
+ final _dummySlots = [
+ TimeSlotModel(isSelected: false, slotId: 1, slot: "11:00"),
+ TimeSlotModel(isSelected: false, slotId: 2, slot: "12:00"),
+ TimeSlotModel(isSelected: true, slotId: 3, slot: "13:00"),
+ TimeSlotModel(isSelected: false, slotId: 4, slot: "14:00"),
+ TimeSlotModel(isSelected: false, slotId: 5, slot: "15:00"),
+ TimeSlotModel(isSelected: false, slotId: 6, slot: "16:00"),
+ TimeSlotModel(isSelected: false, slotId: 7, slot: "17:00"),
+ TimeSlotModel(isSelected: false, slotId: 8, slot: "18:00"),
+ TimeSlotModel(isSelected: false, slotId: 9, slot: "19:00"),
+ TimeSlotModel(isSelected: false, slotId: 10, slot: "20:00"),
+ TimeSlotModel(isSelected: false, slotId: 11, slot: "21:00"),
+ TimeSlotModel(isSelected: false, slotId: 12, slot: "22:00"),
+ TimeSlotModel(isSelected: false, slotId: 13, slot: "23:00"),
+ TimeSlotModel(isSelected: false, slotId: 14, slot: "24:00"),
+ TimeSlotModel(isSelected: false, slotId: 15, slot: "25:00"),
+ TimeSlotModel(isSelected: false, slotId: 16, slot: "26:00"),
+ TimeSlotModel(isSelected: false, slotId: 17, slot: "27:00"),
+ TimeSlotModel(isSelected: false, slotId: 18, slot: "28:00"),
+ TimeSlotModel(isSelected: false, slotId: 19, slot: "29:00"),
+ ];
+
+ void priceBreakDownClicked(BuildContext context) {
+ showModalBottomSheet(
+ context: context,
+ isScrollControlled: true,
+ enableDrag: true,
+ builder: (BuildContext context) {
+ return InfoBottomSheet(
+ title: "Charges Breakdown",
+ description: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Services".toText(fontSize: 16, isBold: true),
+ Column(
+ children: List.generate(
+ 5,
+ (index) => Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "Gear Kit".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
+ "200 SAR".toText(fontSize: 12, isBold: true),
+ ],
),
- if (appointmentsVM.isFetchingServices) ...[
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [const CircularProgressIndicator().paddingAll(10)],
- ),
- ] else if (appointmentsVM.providerServices.isNotEmpty) ...[
- 8.height,
- Builder(
- builder: (context) {
- List serviceCategories = [];
- for (var element in appointmentsVM.providerServices) {
- if (!element.isSelected!) {
- serviceCategories.add(DropValue(element.id?.toInt() ?? 0, element.id.toString(), ""));
- }
- }
- return DropdownField(
- (DropValue value) => appointmentsVM.updateProviderServiceId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)),
- list: serviceCategories,
- hint: "Select Services",
- dropdownValue: appointmentsVM.providerServiceId.selectedId != -1
- ? DropValue(appointmentsVM.providerServiceId.selectedId, appointmentsVM.providerServiceId.selectedOption, "")
- : null,
- );
- },
- ),
- ],
- if (appointmentsVM.providerServiceId.selectedId != -1 && !appointmentsVM.isFetchingServices) ...[
- 16.height,
- Row(
- children: [
- "Select Service Location".toText(
- fontSize: 16,
- isBold: true,
- color: MyColors.black,
- ),
- ],
- ),
- 8.height,
- Row(
- children: [
- Expanded(
- child: ShowFillButton(
- isFilled: appointmentsVM.isHomeTapped,
- maxHeight: 48,
- title: "Home",
- txtColor: appointmentsVM.isHomeTapped ? MyColors.white : MyColors.darkTextColor,
- onPressed: () => appointmentsVM.updateIsHomeTapped(true),
- ),
- ),
- 12.width,
- Expanded(
- child: ShowFillButton(
- isFilled: !appointmentsVM.isHomeTapped,
- txtColor: !appointmentsVM.isHomeTapped ? MyColors.white : MyColors.darkTextColor,
- maxHeight: 48,
- title: "Workshop",
- onPressed: () => appointmentsVM.updateIsHomeTapped(false),
- ),
- ),
- ],
- ),
- if (appointmentsVM.isHomeTapped) ...[
- 8.height,
- TxtField(
- hint: 'Pick Home Location',
- value: appointmentsVM.pickedHomeLocation,
- isNeedClickAll: true,
- postfixData: Icons.location_on,
- postFixDataColor: MyColors.darkTextColor,
- onTap: () {
- //TODO: open the place picked to pick the location and save it in provider.
- appointmentsVM.updatePickedHomeLocation("PM58+F97, Al Olaya, Riyadh 12333");
- },
- ),
- 14.height,
- Row(
- crossAxisAlignment: CrossAxisAlignment.end,
- children: [
- Icon(
- Icons.warning,
- color: MyColors.adPendingStatusColor,
- size: 19,
- ).paddingOnly(bottom: 2),
- 3.width,
- "Some services are not available on home location.".toText(
- color: MyColors.adPendingStatusColor,
- fontSize: 12,
- isItalic: true,
- ),
- ],
- ),
- ]
- ],
+ ),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ "1149 SAR".toText(fontSize: 16, isBold: true),
],
),
- ),
- SizedBox(
- width: double.infinity,
- child: Column(
+ 20.height,
+ "Home Location".toText(fontSize: 16, isBold: true),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
- if (appointmentsVM.isHomeTapped && !appointmentsVM.isFetchingServices) ...[
- const Divider(thickness: 1, height: 1),
- Row(
- crossAxisAlignment: CrossAxisAlignment.end,
- children: [
- // TODO: This Price will be decided according to the service selected
- 150.toString().toText(fontSize: 30, isBold: true),
- "SAR".toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5),
- ],
- ),
- "These charges are additional to the actual service charges. For heavy items the charges may vary.".toText(fontSize: 12, color: MyColors.lightTextColor),
- 22.height,
- ],
- SizedBox(
- width: double.infinity,
- child: ShowFillButton(
- maxHeight: 55,
- title: "Next",
- onPressed: () {},
- ),
- ),
+ "10km ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
+ "5 x 10".toText(fontSize: 12, isBold: true),
],
),
- ).paddingOnly(bottom: 20)
- ],
- )).horPaddingMain();
- },
- );
+ 8.height,
+ Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ "50 SAR".toText(fontSize: 16, isBold: true),
+ ],
+ ),
+ 30.height,
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "Total Amount ".toText(fontSize: 16, isBold: true),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ "120".toText(fontSize: 29, isBold: true),
+ 2.width,
+ "SAR".toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
+ ],
+ )
+ ],
+ ),
+ 30.height,
+ ],
+ ));
+ });
+ }
+
+ String getTotalPrice(List serviceItems) {
+ var totalPrice = 0.0;
+ serviceItems.forEach((element) {
+ totalPrice = totalPrice + double.parse(element.price ?? "0.0");
+ });
+ return totalPrice.toString();
}
@override
@@ -209,117 +147,166 @@ class BookAppointmentServicesView extends StatelessWidget {
children: [
21.height,
CustomAddButton(
- onTap: () => {openTheAddServiceBottomSheet(context)},
+ needsBorder: true,
+ bgColor: MyColors.white,
+ onTap: () => openTheAddServiceBottomSheet(context, appointmentsVM),
text: "Add Services",
- icon: Container(
+ icon: Container(
height: 24,
width: 24,
decoration: const BoxDecoration(shape: BoxShape.circle, color: MyColors.darkTextColor),
child: const Icon(Icons.add, color: MyColors.white),
),
- ),
- // 20.height,
- // ListView.builder(
- // physics: const NeverScrollableScrollPhysics(),
- // shrinkWrap: true,
- // itemCount: adVM.specialServiceCards.length,
- // itemBuilder: (BuildContext context, int index) {
- // SpecialServiceCard specialServicesCard = adVM.specialServiceCards[index];
- // return Column(
- // crossAxisAlignment: CrossAxisAlignment.start,
- // children: [
- // Column(
- // children: [
- // Row(
- // mainAxisAlignment: MainAxisAlignment.spaceBetween,
- // children: [
- // Expanded(
- // child: specialServicesCard.serviceSelectedId!.selectedOption.toText(fontSize: 16, isBold: true),
- // ),
- // Align(
- // alignment: Alignment.topRight,
- // child: MyAssets.closeWithOrangeBg.buildSvg(
- // fit: BoxFit.fill,
- // height: 30,
- // width: 30,
- // ),
- // ).onPress(() => adVM.removeSpecialServiceCard(index))
- // ],
- // ),
- // Builder(builder: (context) {
- // return Column(
- // crossAxisAlignment: CrossAxisAlignment.start,
- // children: [
- // if (specialServicesCard.serviceSelectedId!.selectedId != 1 && specialServicesCard.serviceSelectedId!.selectedId != 3) ...[
- // // Row(
- // // crossAxisAlignment: CrossAxisAlignment.start,
- // // children: [
- // // "Duration: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
- // // (specialServicesCard.duration ?? "").toText(fontSize: 12, isBold: true).expand(),
- // // ],
- // // ),
- // 8.height,
- // Row(
- // crossAxisAlignment: CrossAxisAlignment.start,
- // children: [
- // "Description: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
- // (specialServicesCard.description ?? "").toText(fontSize: 12, isBold: true).expand(),
- // ],
- // ),
- // ],
- // if (specialServicesCard.serviceSelectedId!.selectedId == 1 || specialServicesCard.serviceSelectedId!.selectedId == 3) ...[
- // Row(
- // crossAxisAlignment: CrossAxisAlignment.start,
- // children: [
- // const Icon(
- // weight: 2,
- // Icons.location_on_outlined,
- // color: MyColors.primaryColor,
- // size: 17,
- // ),
- // "${specialServicesCard.duration} km".toText(fontSize: 10, color: MyColors.primaryColor),
- // ],
- // ),
- // 8.height,
- // Row(
- // crossAxisAlignment: CrossAxisAlignment.start,
- // children: [
- // "Branch Address: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
- // (specialServicesCard.address ?? "").toText(fontSize: 12, isBold: true).expand(),
- // ],
- // ),
- // Row(
- // crossAxisAlignment: CrossAxisAlignment.start,
- // children: [
- // "Appointment Time: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
- // "${specialServicesCard.serviceDate} - ${specialServicesCard.serviceTime}".toText(fontSize: 12, isBold: true).expand(),
- // ],
- // ),
- // ],
- // 6.height,
- // Row(
- // crossAxisAlignment: CrossAxisAlignment.end,
- // children: [
- // (specialServicesCard.serviceSelectedId!.itemPrice).toText(fontSize: 20, isBold: true),
- // 2.width,
- // "SAR".toText(color: MyColors.lightTextColor, fontSize: 14),
- // ],
- // ),
- // ],
- // );
- // }),
- // 3.height,
- // const Divider(thickness: 1.5)
- // ],
- // ),
- // 10.height,
- // ],
- // );
- // },
- // ),
+ ).horPaddingMain(),
+ 10.height,
+ ListView.builder(
+ shrinkWrap: true,
+ itemCount: appointmentsVM.serviceAppointmentScheduleList.length,
+ itemBuilder: (BuildContext context, int scheduleIndex) {
+ ServiceAppointmentScheduleModel scheduleData = appointmentsVM.serviceAppointmentScheduleList[scheduleIndex];
+ return Column(
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Expanded(
+ child: "Schedule: ${scheduleIndex + 1}".toText(fontSize: 20, isBold: true),
+ ),
+ Align(
+ alignment: Alignment.topRight,
+ child: Icon(
+ Icons.delete_outline,
+ size: 28,
+ ),
+ ).onPress(() {}),
+ ],
+ ),
+ if (true) ...[
+ 5.height,
+ Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ ("Available Dates").toText(fontSize: 14, isBold: true),
+ ],
+ ),
+ 5.height,
+ SizedBox(
+ width: double.infinity,
+ child: BuildTimeSlots(
+ timeSlots: scheduleData.availableDates!,
+ onPressed: (index) => null,
+ ),
+ ),
+ ],
+ if (scheduleData.selectedDate!.isNotEmpty) ...[
+ 5.height,
+ Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ ("Available Slots").toText(fontSize: 14, isBold: true),
+ ],
+ ),
+ 5.height,
+ SizedBox(
+ width: double.infinity,
+ child: BuildTimeSlots(
+ timeSlots: _dummySlots,
+ onPressed: (index) => null,
+ ),
+ ),
+ ],
+ 20.height,
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ ListView.separated(
+ physics: NeverScrollableScrollPhysics(),
+ shrinkWrap: true,
+ itemCount: appointmentsVM.servicesInSchedule.length,
+ itemBuilder: (BuildContext context, int serviceIndex) {
+ DropValue selectedService = appointmentsVM.servicesInSchedule[serviceIndex];
+ return Column(
+ children: [
+ Row(
+ children: [
+ Expanded(
+ child: selectedService.value.toText(fontSize: 15, isBold: true),
+ ),
+ ],
+ ),
+ if (true) ...[
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Service Location: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
+ ("Home").toText(fontSize: 12, isBold: true).expand(),
+ ],
+ ),
+ 5.height,
+ Column(
+ children: List.generate(scheduleData.serviceItemList!.length, (itemIndex) {
+ ItemData itemData = scheduleData.serviceItemList![itemIndex];
+ return Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "${itemData.name}: ".toText(fontSize: 13, color: MyColors.lightTextColor, isBold: true),
+ ("${itemData.price}").toText(fontSize: 13, isBold: true).expand(),
+ ],
+ );
+ }),
+ ),
+ ],
+ ],
+ );
+ },
+ separatorBuilder: (BuildContext context, int index) => Divider(thickness: 2),
+ ),
+ 8.height,
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ getTotalPrice(appointmentsVM.serviceAppointmentScheduleList[scheduleIndex].serviceItemList ?? []).toText(fontSize: 32, isBold: true),
+ 2.width,
+ "SAR".toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
+ Icon(
+ Icons.arrow_drop_down,
+ size: 30,
+ )
+ ],
+ ).onPress(() => priceBreakDownClicked(context)),
+ ],
+ ),
+ ],
+ ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10));
+ },
+ ).expand(),
+ Row(
+ children: [
+ Expanded(
+ child: ShowFillButton(
+ txtColor: MyColors.black,
+ maxHeight: 55,
+ title: "Cancel",
+ onPressed: () {},
+ backgroundColor: MyColors.greyButtonColor,
+ ),
+ ),
+ 12.width,
+ Expanded(
+ child: ShowFillButton(
+ maxHeight: 55,
+ title: "Review",
+ onPressed: () {
+ navigateWithName(context, AppRoutes.reviewAppointmentView);
+ },
+ backgroundColor: MyColors.darkPrimaryColor,
+ ),
+ )
+ ],
+ ).paddingAll(21)
],
);
},
- ).horPaddingMain());
+ ));
}
}
diff --git a/lib/views/appointments/book_appointments_item_view.dart b/lib/views/appointments/book_appointments_item_view.dart
new file mode 100644
index 0000000..2620166
--- /dev/null
+++ b/lib/views/appointments/book_appointments_item_view.dart
@@ -0,0 +1,147 @@
+import 'package:car_customer_app/view_models/appointments_view_model.dart';
+import 'package:car_customer_app/views/appointments/widgets/service_item_with_price_checkbox.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';
+import 'package:mc_common_app/models/services/item_model.dart';
+import 'package:mc_common_app/theme/colors.dart';
+import 'package:mc_common_app/utils/navigator.dart';
+import 'package:mc_common_app/utils/utils.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/extensions/extensions_widget.dart';
+import 'package:provider/provider.dart';
+
+class BookAppointmentsItemView extends StatelessWidget {
+ const BookAppointmentsItemView({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: CustomAppBar(
+ title: "Select Services",
+ isRemoveBackButton: false,
+ isDrawerEnabled: false,
+ actions: [MyAssets.searchIcon.buildSvg().paddingOnly(right: 21)],
+ onBackButtonTapped: () => Navigator.pop(context),
+ ),
+ body: Consumer(
+ builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Container(
+ height: 40,
+ width: double.infinity,
+ color: MyColors.darkTextColor,
+ alignment: Alignment.centerLeft,
+ child: "${appointmentsVM.selectedSubServicesCounter} Item(s) Selected".toText(fontSize: 16, color: MyColors.white).horPaddingMain(),
+ ),
+ 16.height,
+ Column(
+ children: [
+ "Few services are not available on home location. Change the location to workshop to full access the services".toText(fontSize: 12, isItalic: true, color: MyColors.lightTextColor),
+ 8.height,
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Change location or service: ".toText(fontSize: 14, isBold: true),
+ "Edit".toText(fontSize: 14, isBold: true, isUnderLine: true, color: MyColors.adPendingStatusColor),
+ 5.width,
+ MyAssets.icEdit.buildSvg(width: 17),
+ ],
+ ).onPress(() {}),
+ 16.height,
+ Divider(),
+ ],
+ ).horPaddingMain(),
+ appointmentsVM.serviceItems.isEmpty
+ ? Expanded(child: Center(child: "No Items to show.".toText(fontSize: 16, color: MyColors.lightTextColor)))
+ : ListView.separated(
+ separatorBuilder: (BuildContext context, int index) => Divider(),
+ itemCount: appointmentsVM.serviceItems.length,
+ itemBuilder: (BuildContext context, int index) {
+ ItemData itemData = appointmentsVM.serviceItems[index];
+ return ServiceItemWithPriceCheckBox(
+ description: "Some description about the sub-services",
+ title: itemData.name!,
+ isSelected: itemData.isUpdateOrSelected!,
+ onSelection: (bool value) {
+ appointmentsVM.onItemUpdateOrSelected(index, !itemData.isUpdateOrSelected!, itemData.id!);
+ },
+ priceWidget: Row(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ // TODO: This Price will be decided according to the service selected
+ itemData.price!.split(".").first.toText(fontSize: 30, isBold: true),
+ " SAR".toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5),
+ ],
+ ),
+ );
+ },
+ ).expand(),
+ Column(
+ children: [
+ Divider(
+ height: 1,
+ thickness: 0.7,
+ ),
+ 8.height,
+ if (appointmentsVM.selectSubServicesError != "")
+ Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ appointmentsVM.selectSubServicesError.toText(fontSize: 14, color: Colors.red),
+ ],
+ ).paddingOnly(right: 10),
+ 8.height,
+ Row(
+ children: [
+ Expanded(
+ child: ShowFillButton(
+ txtColor: MyColors.black,
+ maxHeight: 55,
+ title: "Cancel",
+ onPressed: () {
+ appointmentsVM.resetCategorySelectionBottomSheet();
+ pop(context);
+ },
+ backgroundColor: MyColors.greyButtonColor,
+ ),
+ ),
+ 12.width,
+ Expanded(
+ child: Builder(
+ builder: (BuildContext context) {
+ return ShowFillButton(
+ maxHeight: 55,
+ title: "Next",
+ onPressed: () async {
+ bool resp = appointmentsVM.onSubServicesNextPressed();
+ if (resp) {
+ Utils.showLoading(context);
+ await appointmentsVM.mergeServiceIntoAvailableSchedules();
+ appointmentsVM.resetCategorySelectionBottomSheet();
+ Navigator.of(context).pushNamedAndRemoveUntil(AppRoutes.bookAppointmenServicesView, (Route route) => false);
+
+ // appointmentsVM.mergeServiceInAvailableSchedule();
+ }
+ },
+ backgroundColor: !appointmentsVM.isServiceSelectionValidated() ? MyColors.lightTextColor.withOpacity(0.6) : MyColors.primaryColor,
+ );
+ },
+ ),
+ ),
+ ],
+ ).horPaddingMain(),
+ 16.height,
+ ],
+ ),
+ ],
+ );
+ },
+ ));
+ }
+}
diff --git a/lib/views/appointments/review_appointment_view.dart b/lib/views/appointments/review_appointment_view.dart
new file mode 100644
index 0000000..841f4c0
--- /dev/null
+++ b/lib/views/appointments/review_appointment_view.dart
@@ -0,0 +1,325 @@
+import 'package:car_customer_app/view_models/appointments_view_model.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:mc_common_app/classes/consts.dart';
+import 'package:mc_common_app/extensions/int_extensions.dart';
+import 'package:mc_common_app/extensions/string_extensions.dart';
+import 'package:mc_common_app/generated/locale_keys.g.dart';
+import 'package:mc_common_app/models/service_schedule_model.dart';
+import 'package:mc_common_app/models/services/item_model.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/dropdown/dropdow_field.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);
+
+ Widget buildBranchInfoCard({required BuildContext context}) {
+ AppointmentsVM appointmentsVM = context.read();
+ return Padding(
+ padding: const EdgeInsets.only(
+ bottom: 10,
+ left: 21,
+ right: 21,
+ ),
+ child: Row(
+ children: [
+ Image.asset(
+ MyAssets.bnCar,
+ width: 80,
+ height: 60,
+ fit: BoxFit.cover,
+ ),
+ 12.width,
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ (appointmentsVM.selectedBranchModel!.branchName ?? "").toText(fontSize: 16, isBold: true),
+ Row(
+ children: [
+ LocaleKeys.location.tr().toText(color: MyColors.lightTextColor, fontSize: 12),
+ 2.width,
+ ": ${appointmentsVM.selectedBranchModel!.branchDescription ?? ""}".toText(fontSize: 12),
+ ],
+ ),
+ ],
+ ),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ "4.9".toText(
+ isUnderLine: true,
+ isBold: true,
+ fontSize: 12,
+ ),
+ 2.width,
+ MyAssets.starIcon.buildSvg(width: 12),
+ ],
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ],
+ ).onPress(() {}).toWhiteContainer(width: double.infinity, allPading: 12));
+ }
+
+ Widget buildServicesInfoCard({required BuildContext context}) {
+ AppointmentsVM appointmentsVM = context.read();
+ return ListView.builder(
+ shrinkWrap: true,
+ itemCount: appointmentsVM.serviceAppointmentScheduleList.length,
+ itemBuilder: (BuildContext context, int scheduleIndex) {
+ ServiceAppointmentScheduleModel scheduleData = appointmentsVM.serviceAppointmentScheduleList[scheduleIndex];
+ return Column(
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Expanded(
+ child: "Schedule: ${scheduleIndex + 1}".toText(fontSize: 20, isBold: true),
+ ),
+ ],
+ ),
+ 10.height,
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ ListView.separated(
+ physics: NeverScrollableScrollPhysics(),
+ shrinkWrap: true,
+ itemCount: appointmentsVM.servicesInSchedule.length,
+ itemBuilder: (BuildContext context, int serviceIndex) {
+ DropValue selectedService = appointmentsVM.servicesInSchedule[serviceIndex];
+ return Column(
+ children: [
+ Row(
+ children: [
+ Expanded(
+ child: selectedService.value.toText(fontSize: 15, isBold: true),
+ ),
+ ],
+ ),
+ if (true) ...[
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Service Location: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
+ ("Home").toText(fontSize: 12, isBold: true).expand(),
+ ],
+ ),
+ 5.height,
+ Column(
+ children: List.generate(scheduleData.serviceItemList!.length, (itemIndex) {
+ ItemData itemData = scheduleData.serviceItemList![itemIndex];
+ return Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "${itemData.name}: ".toText(fontSize: 13, color: MyColors.lightTextColor, isBold: true),
+ ],
+ );
+ }),
+ ),
+ ],
+ ],
+ );
+ },
+ separatorBuilder: (BuildContext context, int index) => Divider(thickness: 2),
+ ).paddingOnly(bottom: 10),
+ ],
+ ),
+ ],
+ ).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10));
+ },
+ );
+ // AppointmentsVM appointmentsVM = context.read();
+ // return SizedBox(
+ // width: double.infinity,
+ // child: Column(
+ // crossAxisAlignment: CrossAxisAlignment.start,
+ // children: List.generate(
+ // appointmentsVM.servicesInSchedule.length,
+ // (serviceIndex) => Column(
+ // crossAxisAlignment: CrossAxisAlignment.start,
+ // children: [
+ // appointmentsVM.servicesInSchedule[serviceIndex].value.toText(fontSize: 16, isBold: true),
+ // Column(
+ // crossAxisAlignment: CrossAxisAlignment.start,
+ // children: List.generate(
+ // appointmentsVM,
+ // (index) => itemList[index].toText(
+ // fontSize: 12,
+ // color: MyColors.lightTextColor,
+ // isBold: true,
+ // )),
+ // ),
+ // ],
+ // ).paddingOnly(bottom: 14),
+ // ),
+ // ).toWhiteContainer(width: double.infinity, allPading: 12, margin: EdgeInsets.symmetric(horizontal: 21)),
+ // );
+ }
+
+ Widget buildTimeAndLocationInfoCard() {
+ return SizedBox(
+ width: double.infinity,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Time & Location".toText(fontSize: 16, isBold: true),
+ 3.height,
+ Row(children: [
+ "Date & Time: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
+ "2nd Feb, 2023 at 09:30 AM".toText(fontSize: 12, isBold: true),
+ ]),
+ Row(children: [
+ "Location: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
+ "PM58+F97, Al Olaya, Riyadh 12333".toText(fontSize: 12, isBold: true),
+ ]),
+ ],
+ ).toWhiteContainer(width: double.infinity, allPading: 12, margin: EdgeInsets.only(left: 21, right: 21, top: 10)),
+ );
+ }
+
+ Widget buildChargesBreakDown({required BuildContext context}) {
+ AppointmentsVM appointmentsVM = context.read();
+ List allSelectedItems = [];
+ double totalServicePrice = 0.0;
+ appointmentsVM.serviceAppointmentScheduleList.forEach((schedule) {
+ schedule.serviceItemList!.forEach((item) {
+ allSelectedItems.add(item);
+ totalServicePrice = totalServicePrice + double.parse(item.price!);
+ });
+ });
+
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ "Services".toText(fontSize: 16, isBold: true),
+ Column(
+ children: List.generate(
+ allSelectedItems.length,
+ (index) => Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "${allSelectedItems[index].name}".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
+ "${allSelectedItems[index].price} SAR".toText(fontSize: 12, isBold: true),
+ ],
+ ),
+ ),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ "${totalServicePrice.toString()} SAR".toText(fontSize: 16, isBold: true),
+ ],
+ ),
+ 10.height,
+ Divider(thickness: 0.7),
+ "Home Location".toText(fontSize: 16, isBold: true),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "10km ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
+ "5 x 10".toText(fontSize: 12, isBold: true),
+ ],
+ ),
+ 8.height,
+ Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ "50 SAR".toText(fontSize: 16, isBold: true),
+ ],
+ ),
+ 10.height,
+ Divider(
+ thickness: 0.7,
+ ),
+ 10.height,
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ "Total Amount ".toText(fontSize: 16, isBold: true),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ "120".toText(fontSize: 29, isBold: true),
+ 2.width,
+ "SAR".toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
+ ],
+ )
+ ],
+ ),
+ 10.height,
+ ],
+ ).toWhiteContainer(width: double.infinity, allPading: 12, margin: EdgeInsets.only(left: 21, right: 21, top: 10, bottom: 21));
+ }
+
+ Widget buildNextButtonFooter() {
+ return Container(
+ height: 90,
+ color: MyColors.white,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ Divider(thickness: 0.7, height: 3),
+ 10.height,
+ SizedBox(
+ width: double.infinity,
+ child: ShowFillButton(
+ maxHeight: 55,
+ backgroundColor: MyColors.primaryColor,
+ title: "Book Appointment",
+ onPressed: () {},
+ ).paddingOnly(bottom: 12, left: 21, right: 21),
+ ),
+ ],
+ ),
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: CustomAppBar(
+ title: "Review Appointment",
+ isRemoveBackButton: false,
+ isDrawerEnabled: false,
+ actions: [MyAssets.searchIcon.buildSvg().paddingOnly(right: 21)],
+ onBackButtonTapped: () => Navigator.pop(context),
+ ),
+ body: Stack(
+ alignment: Alignment.bottomCenter,
+ children: [
+ SingleChildScrollView(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ buildBranchInfoCard(context: context),
+ buildServicesInfoCard(context: context),
+ buildTimeAndLocationInfoCard(),
+ buildChargesBreakDown(context: context),
+ ],
+ ),
+ ),
+ buildNextButtonFooter(),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/views/appointments/widgets/appointment_service_pick_bottom_sheet.dart b/lib/views/appointments/widgets/appointment_service_pick_bottom_sheet.dart
new file mode 100644
index 0000000..4bab6e6
--- /dev/null
+++ b/lib/views/appointments/widgets/appointment_service_pick_bottom_sheet.dart
@@ -0,0 +1,194 @@
+import 'package:car_customer_app/view_models/appointments_view_model.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/models/widgets_models.dart';
+import 'package:mc_common_app/theme/colors.dart';
+import 'package:mc_common_app/utils/navigator.dart';
+import 'package:mc_common_app/widgets/button/show_fill_button.dart';
+import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
+import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
+import 'package:mc_common_app/widgets/txt_field.dart';
+import 'package:provider/provider.dart';
+
+class AppointmentServicePickBottomSheet extends StatelessWidget {
+ const AppointmentServicePickBottomSheet({Key? key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ AppointmentsVM appointmentsVM = context.watch();
+ return SizedBox(
+ height: MediaQuery.of(context).size.height * 0.85,
+ child: Column(
+ children: [
+ Container(
+ margin: const EdgeInsets.all(8),
+ height: 8,
+ width: 60,
+ decoration: const BoxDecoration(color: MyColors.lightTextColor, borderRadius: BorderRadius.all(Radius.circular(20))),
+ ),
+ 12.height,
+ Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ "Select Category".toText(fontSize: 24, isBold: true),
+ ],
+ ),
+ 30.height,
+ Expanded(
+ child: ListView(
+ children: [
+ Builder(
+ builder: (context) {
+ return DropdownField(
+ (DropValue value) => appointmentsVM.updateProviderCategoryId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)),
+ list: appointmentsVM.branchCategories,
+ hint: "Select Category",
+ dropdownValue: appointmentsVM.branchSelectedCategoryId.selectedId != -1
+ ? DropValue(appointmentsVM.branchSelectedCategoryId.selectedId, appointmentsVM.branchSelectedCategoryId.selectedOption, "")
+ : null,
+ );
+ },
+ ),
+ if (appointmentsVM.isFetchingServices) ...[
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [const CircularProgressIndicator().paddingAll(10)],
+ ),
+ ] else if (appointmentsVM.branchServices.isNotEmpty) ...[
+ 8.height,
+ Builder(
+ builder: (context) {
+ List serviceCategories = [];
+ for (var element in appointmentsVM.branchServices) {
+ if (element.categoryId == appointmentsVM.branchSelectedCategoryId.selectedId) {
+ serviceCategories.add(DropValue(
+ element.serviceProviderServiceId ?? 0,
+ element.serviceDescription!,
+ "",
+ ));
+ }
+ }
+
+ return DropdownField(
+ (DropValue value) => appointmentsVM.updateBranchServiceId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)),
+ list: serviceCategories,
+ hint: "Select Service",
+ dropdownValue: appointmentsVM.branchSelectedServiceId.selectedId != -1
+ ? DropValue(appointmentsVM.branchSelectedServiceId.selectedId, appointmentsVM.branchSelectedServiceId.selectedOption, "")
+ : null,
+ );
+ },
+ ),
+ ],
+ if (appointmentsVM.branchSelectedServiceId.selectedId != -1 && !appointmentsVM.isFetchingServices) ...[
+ 16.height,
+ Row(
+ children: [
+ "Select Service Location".toText(
+ fontSize: 16,
+ isBold: true,
+ color: MyColors.black,
+ ),
+ ],
+ ),
+ 8.height,
+ Row(
+ children: [
+ Expanded(
+ child: ShowFillButton(
+ isFilled: appointmentsVM.isHomeTapped,
+ maxHeight: 48,
+ title: "Home",
+ txtColor: appointmentsVM.isHomeTapped ? MyColors.white : MyColors.darkTextColor,
+ onPressed: () => appointmentsVM.updateIsHomeTapped(true),
+ ),
+ ),
+ 12.width,
+ Expanded(
+ child: ShowFillButton(
+ isFilled: !appointmentsVM.isHomeTapped,
+ txtColor: !appointmentsVM.isHomeTapped ? MyColors.white : MyColors.darkTextColor,
+ maxHeight: 48,
+ title: "Workshop",
+ onPressed: () => appointmentsVM.updateIsHomeTapped(false),
+ ),
+ ),
+ ],
+ ),
+ if (appointmentsVM.isHomeTapped) ...[
+ 8.height,
+ TxtField(
+ hint: 'Pick Home Location',
+ errorValue: appointmentsVM.pickHomeLocationError,
+ value: appointmentsVM.pickedHomeLocation,
+ isNeedClickAll: true,
+ postfixData: Icons.location_on,
+ postFixDataColor: MyColors.darkTextColor,
+ onTap: () {
+ //TODO: open the place picked to pick the location and save it in provider.
+ appointmentsVM.updatePickedHomeLocation("PM58+F97, Al Olaya, Riyadh 12333");
+ },
+ ),
+ 14.height,
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ Icon(
+ Icons.warning,
+ color: MyColors.adPendingStatusColor,
+ size: 19,
+ ).paddingOnly(bottom: 2),
+ 3.width,
+ "Some services are not available on home location.".toText(
+ color: MyColors.adPendingStatusColor,
+ fontSize: 12,
+ isItalic: true,
+ ),
+ ],
+ ),
+ ]
+ ],
+ ],
+ ),
+ ),
+ SizedBox(
+ width: double.infinity,
+ child: Column(
+ children: [
+ if (appointmentsVM.isHomeTapped && !appointmentsVM.isFetchingServices) ...[
+ const Divider(thickness: 1, height: 1),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.end,
+ children: [
+ // TODO: This Price will be decided according to the service selected
+ 150.toString().toText(fontSize: 30, isBold: true),
+ "SAR".toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5),
+ ],
+ ),
+ "These charges are additional to the actual service charges. For heavy items the charges may vary.".toText(fontSize: 12, color: MyColors.lightTextColor),
+ 22.height,
+ ],
+ SizedBox(
+ width: double.infinity,
+ child: ShowFillButton(
+ maxHeight: 55,
+ backgroundColor: !appointmentsVM.isServiceSelectionValidated() ? MyColors.lightTextColor.withOpacity(0.6) : MyColors.primaryColor,
+ title: "Next",
+ onPressed: () {
+ bool isValidated = appointmentsVM.isServiceSelectionValidated();
+ if (isValidated) {
+ appointmentsVM.getServiceItems(appointmentsVM.branchSelectedServiceId.selectedId);
+ navigateWithName(context, AppRoutes.bookAppointmentsItemView);
+ }
+ },
+ ),
+ ),
+ ],
+ ),
+ ).paddingOnly(bottom: 20)
+ ],
+ )).horPaddingMain();
+ }
+}
diff --git a/lib/views/appointments/widgets/service_item_with_price_checkbox.dart b/lib/views/appointments/widgets/service_item_with_price_checkbox.dart
new file mode 100644
index 0000000..f8269c6
--- /dev/null
+++ b/lib/views/appointments/widgets/service_item_with_price_checkbox.dart
@@ -0,0 +1,51 @@
+import 'package:flutter/material.dart';
+import 'package:mc_common_app/extensions/string_extensions.dart';
+import 'package:mc_common_app/theme/colors.dart';
+import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
+
+class ServiceItemWithPriceCheckBox extends StatelessWidget {
+ final bool isSelected;
+ final String title, description;
+ final Widget priceWidget;
+
+ final Function(bool) onSelection;
+
+ const ServiceItemWithPriceCheckBox({
+ required this.isSelected,
+ required this.title,
+ required this.description,
+ this.priceWidget = const SizedBox(),
+ required this.onSelection,
+ Key? key,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return SizedBox(
+ width: double.infinity,
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ Checkbox(
+ value: isSelected,
+ onChanged: (bool? v) {
+ onSelection(v ?? false);
+ },
+ ),
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ title.toText(fontSize: 16, isBold: true).paddingOnly(top: 10),
+ description.toText(fontSize: 12, color: MyColors.lightTextColor),
+ priceWidget,
+ ],
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/views/dashboard/dashboard_page.dart b/lib/views/dashboard/dashboard_page.dart
index 1c9fa86..7145d88 100644
--- a/lib/views/dashboard/dashboard_page.dart
+++ b/lib/views/dashboard/dashboard_page.dart
@@ -2,16 +2,17 @@ import 'dart:async';
import 'package:car_customer_app/view_models/appointments_view_model.dart';
import 'package:car_customer_app/view_models/dashboard_view_model.dart';
-import 'package:car_customer_app/view_models/providers_view_model.dart';
import 'package:car_customer_app/views/dashboard/fragments/ads_fragment.dart';
import 'package:car_customer_app/views/dashboard/fragments/appointments_fragment.dart';
import 'package:car_customer_app/views/dashboard/fragments/home_fragment.dart';
-import 'package:car_customer_app/views/dashboard/fragments/providers_fragment.dart';
import 'package:car_customer_app/views/dashboard/fragments/settings_fragment.dart';
import 'package:car_customer_app/views/dashboard/widgets/bottom_nav_bar.dart';
import 'package:car_customer_app/views/dashboard/widgets/drawer_widget.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/models/widgets_models.dart';
+import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
@@ -36,9 +37,9 @@ class _DashboardPageState extends State {
fetchUsername();
scheduleMicrotask(() {
context.read().populateAppointmentsFilterList();
- context.read().populateProvidersFilterList();
+ context.read().populateProvidersFilterList();
context.read().populateAdsFilterList();
- context.read().getAllNearBranches();
+ context.read().getAllNearBranches();
_onRefresh();
});
}
@@ -55,6 +56,22 @@ class _DashboardPageState extends State {
if (adVm.exploreAds.isEmpty) {
await adVm.getExploreAds();
}
+
+ final adVM = context.read();
+ if (adVM.vehicleTypes.isEmpty) {
+ await adVM.getVehicleTypes();
+ }
+
+ if (adVM.vehicleAdsDurations.isEmpty) {
+ await adVM.getVehicleAdsDuration();
+ }
+ adVM.updateVehicleAdDurationId(
+ SelectionModel(
+ selectedId: adVM.vehicleAdsDurations.first.id ?? 0,
+ selectedOption: "${adVM.vehicleAdsDurations.first.days} Days",
+ itemPrice: adVM.vehicleAdsDurations.first.price!.toInt().toString(),
+ ),
+ );
}
fetchUsername() async {}
@@ -69,7 +86,7 @@ class _DashboardPageState extends State {
String getPageTitle(int index) {
if (index == 0) {
- return "Branchs";
+ return "Branches";
}
if (index == 1) {
return "Appointments";
@@ -89,6 +106,7 @@ class _DashboardPageState extends State {
@override
Widget build(BuildContext context) {
bool isHomePage = context.watch().selectedNavbarBarIndex == 2;
+ bool isAdsPage = context.watch().selectedNavbarBarIndex == 3;
return Scaffold(
appBar: CustomAppBar(
backgroundColor: null,
@@ -97,7 +115,15 @@ class _DashboardPageState extends State {
profileImageUrl: MyAssets.bnCar,
isRemoveBackButton: true,
isDrawerEnabled: isHomePage ? true : false,
- actions: [(isHomePage ? MyAssets.notificationsBellIcon : MyAssets.searchIcon).buildSvg().paddingOnly(right: 21)],
+ actions: [
+ (isHomePage
+ ? MyAssets.notificationsBellIcon.buildSvg()
+ : InkWell(
+ onTap: () => navigateWithName(context, AppRoutes.adsSearchFilterScreen),
+ child: MyAssets.searchIcon.buildSvg(),
+ ))
+ .paddingOnly(right: 21)
+ ],
),
drawer: CustomDrawer(dashboardVM: context.watch()),
bottomNavigationBar: CustomBottomNavbar(),
diff --git a/lib/views/dashboard/fragments/ads_fragment.dart b/lib/views/dashboard/fragments/ads_fragment.dart
index d13952c..0bfc170 100644
--- a/lib/views/dashboard/fragments/ads_fragment.dart
+++ b/lib/views/dashboard/fragments/ads_fragment.dart
@@ -1,8 +1,13 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
+import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
+import 'package:mc_common_app/extensions/string_extensions.dart';
+import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart';
+import 'package:mc_common_app/models/widgets_models.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/ad_view_model.dart';
import 'package:mc_common_app/views/advertisement/ads_list.dart';
@@ -20,6 +25,16 @@ class AdsFragment extends StatelessWidget {
await adVM.getMyAds();
}
+ List getAdsList(AdVM adVM) {
+ if (adVM.isExploreAdsTapped) {
+ return adVM.exploreAdsFilteredList;
+ }
+ if (adVM.myAdsFilteredList.isNotEmpty) {
+ return adVM.myAdsFilteredList;
+ }
+ return [];
+ }
+
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -62,18 +77,21 @@ class AdsFragment extends StatelessWidget {
),
],
).horPaddingMain(),
- if (adVM.isExploreAdsTapped && adVM.exploreAds.isNotEmpty) ...[
+ if (adVM.isExploreAdsTapped) ...[
16.height,
- FiltersList(filterList: adVM.exploreAdsFilterOptions, onFilterTapped: (index, selectedFilterId) => adVM.applyFilterOnExploreAds(index: index), needLeftPadding: false)
+ FiltersList(
+ filterList: adVM.exploreAdsFilterOptions,
+ onFilterTapped: (index, selectedFilterId) => adVM.applyFilterOnExploreAds(index: index, createdByRoleFilter: selectedFilterId.toCreatedByRoleEnum()),
+ needLeftPadding: false)
.paddingOnly(left: 21),
],
- if (!adVM.isExploreAdsTapped && adVM.myAds.isNotEmpty) ...[
+ if (!adVM.isExploreAdsTapped) ...[
16.height,
FiltersList(
- filterList: adVM.myAdsFilterOptions,
- onFilterTapped: (index, selectedFilterId) => adVM.applyFilterOnMyAds(index: index, selectedFilterId: selectedFilterId),
- needLeftPadding: false)
- .paddingOnly(left: 21),
+ filterList: adVM.myAdsFilterOptions,
+ onFilterTapped: (index, selectedFilterId) => adVM.applyFilterOnMyAds(index: index, adPostStatusEnum: selectedFilterId.toAdPostEnum()),
+ needLeftPadding: false,
+ ).paddingOnly(left: 21),
],
],
);
@@ -85,15 +103,7 @@ class AdsFragment extends StatelessWidget {
onRefresh: () => onRefreshAds(context),
child: Consumer(
builder: (BuildContext context, AdVM adVM, Widget? child) {
- return BuildAdsList(
- isAdsFragment: true,
- shouldShowAdStatus: !adVM.isExploreAdsTapped,
- adsList: adVM.isExploreAdsTapped && adVM.exploreAdsFilteredList.isNotEmpty
- ? adVM.exploreAdsFilteredList
- : !adVM.isExploreAdsTapped && adVM.myAdsFilteredList.isNotEmpty
- ? adVM.myAdsFilteredList
- : [],
- );
+ return BuildAdsList(isAdsFragment: true, shouldShowAdStatus: !adVM.isExploreAdsTapped, adsList: getAdsList(adVM));
},
),
),
@@ -102,10 +112,8 @@ class AdsFragment extends StatelessWidget {
),
),
floatingActionButton: FloatingActionButton(
- onPressed: () {
- context.read().getVehicleTypes();
-
- navigateWithName(context, AppRoutes.createAdView);
+ onPressed: () async {
+ navigateWithName(context, AppRoutes.selectAdTypeView, arguments: injector.get().currentAppType == AppType.provider);
},
backgroundColor: MyColors.darkPrimaryColor,
child: Icon(
diff --git a/lib/views/dashboard/fragments/appointments_fragment.dart b/lib/views/dashboard/fragments/appointments_fragment.dart
index 137ae1e..aff1704 100644
--- a/lib/views/dashboard/fragments/appointments_fragment.dart
+++ b/lib/views/dashboard/fragments/appointments_fragment.dart
@@ -41,7 +41,11 @@ class AppointmentsFragment extends StatelessWidget {
itemCount: appointmentsVM.myAppointments.length,
itemBuilder: (BuildContext context, int index) {
return BuildAppointmentContainerForCustomer(
- onTapped: () => navigateWithName(context, AppRoutes.appointmentDetailView, arguments: appointmentsVM.myAppointments[index]),
+ onTapped: () => navigateWithName(
+ context,
+ AppRoutes.appointmentDetailView,
+ arguments: appointmentsVM.myAppointments[index],
+ ),
appointmentListModel: appointmentsVM.myAppointments[index],
);
},
diff --git a/lib/views/dashboard/fragments/branches_fragment.dart b/lib/views/dashboard/fragments/branches_fragment.dart
index d0ab34c..792202f 100644
--- a/lib/views/dashboard/fragments/branches_fragment.dart
+++ b/lib/views/dashboard/fragments/branches_fragment.dart
@@ -1,17 +1,18 @@
-import 'package:car_customer_app/view_models/providers_view_model.dart';
+import 'package:car_customer_app/view_models/appointments_view_model.dart';
+import 'package:easy_localization/easy_localization.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';
import 'package:mc_common_app/generated/locale_keys.g.dart';
+import 'package:mc_common_app/models/provider_branches_models/branch_detail_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/widgets/common_widgets/categories_list.dart';
import 'package:mc_common_app/widgets/common_widgets/provider_details_card.dart';
import 'package:provider/provider.dart';
-import 'package:easy_localization/easy_localization.dart';
class BranchesFragment extends StatelessWidget {
const BranchesFragment({Key? key}) : super(key: key);
@@ -23,53 +24,53 @@ class BranchesFragment extends StatelessWidget {
width: double.infinity,
height: double.infinity,
child: Consumer(
- builder: (BuildContext context, ProvidersVM providersVM, Widget? child) {
+ builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
return Column(
children: [
16.height,
FiltersList(
- filterList: providersVM.providersFilterOptions,
- onFilterTapped: (index, selectedFilterId) => providersVM.applyFilterOnProviders(index: index),
+ filterList: appointmentsVM.providersFilterOptions,
+ onFilterTapped: (index, selectedFilterId) => appointmentsVM.applyFilterOnProviders(index: index),
),
16.height,
Expanded(
child: RefreshIndicator(
onRefresh: () async {
- context.read().getAllNearBranches(isNeedToRebuild: true);
+ context.read().getAllNearBranches(isNeedToRebuild: true);
},
child: SingleChildScrollView(
child: Container(
width: double.infinity,
height: MediaQuery.of(context).size.height / 1.37,
- child: Consumer(
+ child: Consumer(
builder: (context, model, _) {
if (model.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
- return model.branches?.data == null
- ? const Center(child: Text("No Branch Found"))
- : model.branches!.data!.isEmpty
- ? Center(child: Text(LocaleKeys.no_branch.tr()))
- : ListView.separated(
- itemBuilder: (context, index) {
- return ProviderDetailsCard(
- onCardTapped: () {
- navigateWithName(context, AppRoutes.branchDetailPage, arguments: model.branches!.data![index]);
- },
- providerImageUrl: MyAssets.bnCar,
- title: model.branches!.data![index].branchName ?? "",
- providerLocation: model.branches!.data![index].distanceKm.toString() + " KM",
- providerName: model.branches!.data![index].serviceProviderName ?? "",
- providerRatings: "4.9",
- items: model.branches!.data![index].branchServices,
- );
- },
- separatorBuilder: (context, index) {
- return 12.height;
+ return model.nearbyBranches.isEmpty
+ ? Center(child: LocaleKeys.no_branch.tr().toText(fontSize: 16, color: MyColors.lightTextColor))
+ : ListView.separated(
+ itemCount: model.nearbyBranches.length,
+ itemBuilder: (context, index) {
+ BranchDetailModel branchDetailModel = model.nearbyBranches[index];
+
+ return ProviderDetailsCard(
+ onCardTapped: () {
+ navigateWithName(context, AppRoutes.branchDetailPage, arguments: branchDetailModel);
},
- itemCount: model.branches!.data!.length,
- padding: const EdgeInsets.all(12),
+ providerImageUrl: MyAssets.bnCar,
+ title: branchDetailModel.branchName ?? "",
+ providerLocation: branchDetailModel.distanceKm.toString() + " KM",
+ providerName: branchDetailModel.serviceProviderName ?? "",
+ providerRatings: "4.9",
+ services: branchDetailModel.branchServices,
);
+ },
+ separatorBuilder: (context, index) {
+ return 12.height;
+ },
+ padding: const EdgeInsets.all(12),
+ );
}
},
),
diff --git a/lib/views/dashboard/fragments/home_fragment.dart b/lib/views/dashboard/fragments/home_fragment.dart
index c7c4d6b..6a219cc 100644
--- a/lib/views/dashboard/fragments/home_fragment.dart
+++ b/lib/views/dashboard/fragments/home_fragment.dart
@@ -1,10 +1,10 @@
import 'package:car_customer_app/view_models/appointments_view_model.dart';
import 'package:car_customer_app/view_models/dashboard_view_model.dart';
-import 'package:car_customer_app/view_models/providers_view_model.dart';
import 'package:car_customer_app/views/appointments/widgets/customer_appointment_slider_widget.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/extensions/int_extensions.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/views/advertisement/ads_list.dart';
import 'package:mc_common_app/widgets/common_widgets/my_service_provider.dart';
@@ -43,7 +43,7 @@ class HomeFragment extends StatelessWidget {
onSubtitleTapped: () {
print("value: ${AppState().getUser.data!.accessToken}");
context.read().onNavbarTapped(0);
- context.read().applyFilterOnProviders(index: 0);
+ context.read().applyFilterOnProviders(index: 0);
}).horPaddingMain(),
const ServiceProviderWidget().horPaddingMain(),
Consumer(
@@ -80,7 +80,7 @@ class HomeFragment extends StatelessWidget {
onSubtitleTapped: () {
context.read().onNavbarTapped(3);
context.read().updateIsExploreAds(true);
- context.read().applyFilterOnExploreAds(index: 0);
+ context.read().applyFilterOnExploreAds(index: 0, createdByRoleFilter: CreatedByRoleEnum.allAds);
},
).horPaddingMain(),
BuildAdsList(
diff --git a/lib/views/dashboard/fragments/providers_fragment.dart b/lib/views/dashboard/fragments/providers_fragment.dart
index 09e6dab..f2f7593 100644
--- a/lib/views/dashboard/fragments/providers_fragment.dart
+++ b/lib/views/dashboard/fragments/providers_fragment.dart
@@ -1,61 +1,60 @@
-import 'package:car_customer_app/view_models/appointments_view_model.dart';
-import 'package:car_customer_app/view_models/providers_view_model.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/theme/colors.dart';
-import 'package:mc_common_app/utils/navigator.dart';
-import 'package:mc_common_app/widgets/common_widgets/categories_list.dart';
-import 'package:mc_common_app/widgets/common_widgets/provider_details_card.dart';
-import 'package:provider/provider.dart';
-
-class ProvidersFragment extends StatelessWidget {
- const ProvidersFragment({Key? key}) : super(key: key);
-
- @override
- Widget build(BuildContext context) {
- return Container(
- color: MyColors.backgroundColor,
- width: double.infinity,
- height: double.infinity,
- child: Consumer(
- builder: (BuildContext context, ProvidersVM providersVM, Widget? child) {
- return Column(
- children: [
- 16.height,
- FiltersList(
- filterList: providersVM.providersFilterOptions,
- onFilterTapped: (index, selectedFilterId) => providersVM.applyFilterOnProviders(index: index),
- ),
- 16.height,
- Expanded(
- child: Container(
- child: ListView.builder(
- shrinkWrap: true,
- itemCount: 30,
- itemBuilder: (BuildContext context, int index) {
- return ProviderDetailsCard(
- onCardTapped: () {
- if (context.read().providerCategories.isEmpty) {
- context.read().getProviderCategories();
- }
- navigateWithName(context, AppRoutes.bookAppointmenServicesView);
- },
- providerImageUrl: MyAssets.bnCar,
- title:"",
- providerLocation: " 3km",
- providerName: "Al Ahmed Maintenance",
- providerRatings: "4.9",
- );
- },
- ),
- ),
- ),
- ],
- );
- },
- ),
- );
- }
-}
+// import 'package:car_customer_app/view_models/appointments_view_model.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/theme/colors.dart';
+// import 'package:mc_common_app/utils/navigator.dart';
+// import 'package:mc_common_app/widgets/common_widgets/categories_list.dart';
+// import 'package:mc_common_app/widgets/common_widgets/provider_details_card.dart';
+// import 'package:provider/provider.dart';
+//
+// class ProvidersFragment extends StatelessWidget {
+// const ProvidersFragment({Key? key}) : super(key: key);
+//
+// @override
+// Widget build(BuildContext context) {
+// return Container(
+// color: MyColors.backgroundColor,
+// width: double.infinity,
+// height: double.infinity,
+// child: Consumer(
+// builder: (BuildContext context, AppointmentsVM appointmentsVM, Widget? child) {
+// return Column(
+// children: [
+// 16.height,
+// FiltersList(
+// filterList: appointmentsVM.providersFilterOptions,
+// onFilterTapped: (index, selectedFilterId) => appointmentsVM.applyFilterOnProviders(index: index),
+// ),
+// 16.height,
+// Expanded(
+// child: Container(
+// child: ListView.builder(
+// shrinkWrap: true,
+// itemCount: 30,
+// itemBuilder: (BuildContext context, int index) {
+// return ProviderDetailsCard(
+// onCardTapped: () {
+// if (context.read().branchCategories.isEmpty) {
+// context.read().getBranchCategories();
+// }
+// navigateWithName(context, AppRoutes.bookAppointmenServicesView);
+// },
+// providerImageUrl: MyAssets.bnCar,
+// title: "",
+// providerLocation: " 3km",
+// providerName: "Al Ahmed Maintenance",
+// providerRatings: "4.9",
+// );
+// },
+// ),
+// ),
+// ),
+// ],
+// );
+// },
+// ),
+// );
+// }
+// }
diff --git a/lib/views/provider/branch_detail_page.dart b/lib/views/provider/branch_detail_page.dart
index dbace34..34092a3 100644
--- a/lib/views/provider/branch_detail_page.dart
+++ b/lib/views/provider/branch_detail_page.dart
@@ -1,24 +1,25 @@
+import 'package:car_customer_app/view_models/appointments_view_model.dart';
import 'package:car_customer_app/views/provider/sheet/items_list_sheet.dart';
+import 'package:easy_localization/easy_localization.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';
import 'package:mc_common_app/generated/locale_keys.g.dart';
-import 'package:mc_common_app/models/services/branch_model.dart';
-import 'package:easy_localization/easy_localization.dart';
-import 'package:mc_common_app/models/services/service_model.dart';
+import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/widgets/bottom_sheet.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/extensions/extensions_widget.dart';
+import 'package:provider/provider.dart';
class BranchDetailPage extends StatefulWidget {
- BranchModel branchModel;
+ final BranchDetailModel branchDetailModel;
- BranchDetailPage({required this.branchModel});
+ BranchDetailPage({required this.branchDetailModel});
@override
State createState() => _BranchDetailPageState();
@@ -29,7 +30,7 @@ class _BranchDetailPageState extends State {
void initState() {
// TODO: implement initState
super.initState();
- if (widget.branchModel.branchServices!.length > 0) widget.branchModel.branchServices?.first.isExpanded = true;
+ if (widget.branchDetailModel.branchServices!.length > 0) widget.branchDetailModel.branchServices?.first.isExpandedOrSelected = true;
}
@override
@@ -52,7 +53,7 @@ class _BranchDetailPageState extends State {
children: [
Image.asset(MyAssets.bnCar),
12.height,
- "${widget.branchModel.branchName} | ${widget.branchModel.serviceProviderName}".toString().toText(
+ "${widget.branchDetailModel.branchName} | ${widget.branchDetailModel.serviceProviderName}".toString().toText(
fontSize: 16,
isBold: true,
),
@@ -60,14 +61,14 @@ class _BranchDetailPageState extends State {
children: [
(LocaleKeys.location.tr() + ":").toText(color: MyColors.lightTextColor, fontSize: 12),
4.width,
- (widget.branchModel.distanceKm.toString() + " km").toText(fontSize: 12, isBold: true),
+ (widget.branchDetailModel.distanceKm.toString() + " km").toText(fontSize: 12, isBold: true),
],
),
Row(
children: [
("Time" + ":").toText(color: MyColors.lightTextColor, fontSize: 12),
4.width,
- "${widget.branchModel.openTime} - ${widget.branchModel.closeTime}".toText(fontSize: 12, isBold: true),
+ "${widget.branchDetailModel.openTime} - ${widget.branchDetailModel.closeTime}".toText(fontSize: 12, isBold: true),
],
),
2.height,
@@ -123,7 +124,7 @@ class _BranchDetailPageState extends State {
)
.onPress(
() {
- navigateWithName(context, AppRoutes.providerProfilePage, arguments: widget.branchModel.serviceProviderId);
+ navigateWithName(context, AppRoutes.providerProfilePage, arguments: widget.branchDetailModel.serviceProviderId);
},
),
],
@@ -134,7 +135,7 @@ class _BranchDetailPageState extends State {
color: MyColors.lightTextColor,
isBold: true,
),
- if (widget.branchModel.branchServices!.length == 0) "No Services Available".toText(fontSize: 12, isBold: true),
+ if (widget.branchDetailModel.branchServices!.length == 0) "No Services Available".toText(fontSize: 12, isBold: true),
showServicesList(),
],
).toWhiteContainer(
@@ -150,11 +151,11 @@ class _BranchDetailPageState extends State {
title: "Book Appointment",
maxWidth: double.infinity,
margin: EdgeInsets.all(21),
- onPressed: () {},
- ).toContainer(
- paddingAll: 0,
- backgroundColor: Colors.white,
- ),
+ onPressed: () {
+ navigateWithName(context, AppRoutes.bookAppointmenServicesView);
+ context.read().updateSelectedBranch(widget.branchDetailModel);
+ },
+ ).toContainer(paddingAll: 0, backgroundColor: Colors.white),
],
),
);
@@ -165,7 +166,7 @@ class _BranchDetailPageState extends State {
itemBuilder: (context, index) {
return ExpansionTile(
tilePadding: EdgeInsets.zero,
- title: (widget.branchModel.branchServices![index].serviceDescription ?? "").toText(
+ title: (widget.branchDetailModel.branchServices![index].serviceDescription ?? "").toText(
fontSize: 16,
isBold: true,
),
@@ -173,11 +174,11 @@ class _BranchDetailPageState extends State {
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
- showItem("Allowing home service:", (widget.branchModel.branchServices![index].isAllowAppointment ?? false) ? "Yes" : "No", valueColor: Colors.green),
- showItem("Home service range", widget.branchModel.branchServices![index].customerLocationRange.toString() + "KM"),
- showItem("Charges per KM", widget.branchModel.branchServices![index].customerLocationRange.toString() + "SAR"),
+ showItem("Allowing home service:", (widget.branchDetailModel.branchServices![index].isAllowAppointment ?? false) ? "Yes" : "No", valueColor: Colors.green),
+ showItem("Home service range", widget.branchDetailModel.branchServices![index].customerLocationRange.toString() + "KM"),
+ showItem("Charges per KM", widget.branchDetailModel.branchServices![index].customerLocationRange.toString() + "SAR"),
8.height,
- (widget.branchModel.branchServices![index].itemsCount.toString() + "+ items").toText(
+ (widget.branchDetailModel.branchServices![index].itemsCount.toString() + "+ items").toText(
fontSize: 12,
isBold: true,
color: MyColors.primaryColor,
@@ -186,18 +187,18 @@ class _BranchDetailPageState extends State {
20.height,
],
).onPress(() {
- showMyBottomSheet(context, child: ItemsListSheet(widget.branchModel.branchServices![index].serviceProviderServiceId ?? 0));
+ showMyBottomSheet(context, child: ItemsListSheet(widget.branchDetailModel.branchServices![index].serviceProviderServiceId ?? 0));
}),
],
onExpansionChanged: (value) {
setState(() {
- widget.branchModel.branchServices![index].isExpanded = value;
+ widget.branchDetailModel.branchServices![index].isExpandedOrSelected = value;
});
},
backgroundColor: Colors.transparent,
collapsedBackgroundColor: Colors.transparent,
- initiallyExpanded: widget.branchModel.branchServices![index].isExpanded,
- trailing: widget.branchModel.branchServices![index].isExpanded ? Icon(Icons.keyboard_arrow_up) : Icon(Icons.keyboard_arrow_down),
+ initiallyExpanded: widget.branchDetailModel.branchServices![index].isExpandedOrSelected,
+ trailing: widget.branchDetailModel.branchServices![index].isExpandedOrSelected ? Icon(Icons.keyboard_arrow_up) : Icon(Icons.keyboard_arrow_down),
);
},
separatorBuilder: (context, index) {
@@ -205,7 +206,7 @@ class _BranchDetailPageState extends State {
height: 1,
);
},
- itemCount: widget.branchModel.branchServices!.length,
+ itemCount: widget.branchDetailModel.branchServices!.length,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
);
diff --git a/lib/views/provider/provider_profile_page.dart b/lib/views/provider/provider_profile_page.dart
index a16f39f..3071156 100644
--- a/lib/views/provider/provider_profile_page.dart
+++ b/lib/views/provider/provider_profile_page.dart
@@ -1,4 +1,5 @@
-import 'package:car_customer_app/view_models/providers_view_model.dart';
+import 'package:car_customer_app/view_models/appointments_view_model.dart';
+import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/routes.dart';
@@ -12,10 +13,9 @@ import 'package:mc_common_app/widgets/common_widgets/provider_details_card.dart'
import 'package:mc_common_app/widgets/empty_widget.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
-import 'package:easy_localization/easy_localization.dart';
class ProviderProfilePage extends StatefulWidget {
- int providerId;
+ final int providerId;
ProviderProfilePage({required this.providerId});
@@ -27,7 +27,7 @@ class _ProviderProfilePageState extends State {
@override
void initState() {
super.initState();
- context.read().getBranchAndServices(widget.providerId ?? 0);
+ context.read().getBranchAndServices(widget.providerId);
}
@override
@@ -40,11 +40,11 @@ class _ProviderProfilePageState extends State {
width: double.infinity,
height: double.infinity,
padding: EdgeInsets.all(21),
- child: Consumer(
+ child: Consumer(
builder: (context, model, _) {
- return model.providerModel == null
+ return model.providerProfileModel == null
? const Center(child: CircularProgressIndicator())
- : model.providerModel!.data == null
+ : model.providerProfileModel == null
? const EmptyWidget()
: SingleChildScrollView(
child: Column(
@@ -55,7 +55,7 @@ class _ProviderProfilePageState extends State {
//TODO: company logo/banner not added form provider app yet
Image.asset(MyAssets.bnCar),
12.height,
- model.providerModel!.data!.companyName.toString().toText(
+ model.providerProfileModel!.companyName.toString().toText(
fontSize: 16,
isBold: true,
),
@@ -77,28 +77,28 @@ class _ProviderProfilePageState extends State {
allPading: 12,
),
12.height,
- model.providerModel!.data!.serviceProviderBranch == null
+ model.providerProfileModel!.serviceProviderBranch == null
? const Center(child: Text("No Branch Found"))
- : model.providerModel!.data!.serviceProviderBranch!.isEmpty
+ : model.providerProfileModel!.serviceProviderBranch!.isEmpty
? Center(child: Text(LocaleKeys.no_branch.tr()))
: ListView.separated(
itemBuilder: (context, index) {
return ProviderDetailsCard(
onCardTapped: () {
- navigateWithName(context, AppRoutes.branchDetailPage, arguments: model.providerModel!.data!.serviceProviderBranch![index]);
+ navigateWithName(context, AppRoutes.branchDetailPage, arguments: model.providerProfileModel!.serviceProviderBranch![index]);
},
providerImageUrl: MyAssets.bnCar,
- title: model.providerModel!.data!.serviceProviderBranch![index].branchName ?? "",
- providerLocation: model.providerModel!.data!.serviceProviderBranch![index].distanceKm.toString() + " KM",
- providerName: model.providerModel!.data!.serviceProviderBranch![index].serviceProviderName ?? "",
+ title: model.providerProfileModel!.serviceProviderBranch![index].branchName ?? "",
+ providerLocation: model.providerProfileModel!.serviceProviderBranch![index].distanceKm.toString() + " KM",
+ providerName: model.providerProfileModel!.serviceProviderBranch![index].serviceProviderName ?? "",
providerRatings: "4.9",
- items: model.providerModel!.data!.serviceProviderBranch![index].branchServices,
+ services: model.providerProfileModel!.serviceProviderBranch![index].branchServices,
);
},
separatorBuilder: (context, index) {
return 12.height;
},
- itemCount: model.providerModel!.data!.serviceProviderBranch!.length,
+ itemCount: model.providerProfileModel!.serviceProviderBranch!.length,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
)
diff --git a/lib/views/provider/sheet/items_list_sheet.dart b/lib/views/provider/sheet/items_list_sheet.dart
index 63a8fbf..4738e2d 100644
--- a/lib/views/provider/sheet/items_list_sheet.dart
+++ b/lib/views/provider/sheet/items_list_sheet.dart
@@ -1,19 +1,15 @@
-import 'package:flutter_svg/flutter_svg.dart';
-import 'package:flutter/cupertino.dart';
+import 'package:car_customer_app/view_models/appointments_view_model.dart';
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/models/services/item_model.dart';
import 'package:mc_common_app/theme/colors.dart';
-import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/widgets/empty_widget.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
-import '../../../view_models/providers_view_model.dart';
-
class ItemsListSheet extends StatefulWidget {
- int serviceId;
+ final int serviceId;
ItemsListSheet(this.serviceId);
@@ -25,74 +21,70 @@ class _ItemsListSheetState extends State {
@override
void initState() {
super.initState();
- context.read().getServiceItems(widget.serviceId ?? 0);
+ context.read().getServiceItems(widget.serviceId);
}
@override
Widget build(BuildContext context) {
return SizedBox(
height: MediaQuery.of(context).size.height / 1.2,
- child: Consumer(
- builder: (context, model, _) {
- return model.serviceItems == null
- ? const Center(child: CircularProgressIndicator())
- : model.serviceItems!.data!.isEmpty
- ? const EmptyWidget()
- : ListView.separated(
- itemBuilder: (BuildContext context, int index) {
- return SizedBox(
- width: double.infinity,
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: MainAxisAlignment.start,
- children: [
- Expanded(
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- mainAxisAlignment: MainAxisAlignment.start,
+ child: Consumer(
+ builder: (context, appointmentsVM, _) {
+ return appointmentsVM.serviceItems.isEmpty
+ ? const EmptyWidget()
+ : ListView.separated(
+ itemCount: appointmentsVM.serviceItems.length,
+ itemBuilder: (BuildContext context, int index) {
+ ItemData serviceItemModel = appointmentsVM.serviceItems[index];
+ return SizedBox(
+ width: double.infinity,
+ child: Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ serviceItemModel.toString().toText(fontSize: 16, isBold: true),
+ 4.height,
+ showItem("Available for appointment:", (serviceItemModel.isAllowAppointment ?? false) ? "Yes" : "No", valueColor: Colors.green),
+ showItem("Allowing Workshop service:", (serviceItemModel.isAppointmentCompanyLoc ?? false) ? "Yes" : "No", valueColor: Colors.green),
+ showItem("Allowing home service:", (serviceItemModel.isAppointmentCustomerLoc ?? false) ? "Yes" : "No", valueColor: Colors.green),
+ 12.height,
+ "Service Amount".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.end,
children: [
- model.serviceItems!.data![index].name.toString().toText(fontSize: 16, isBold: true),
- 4.height,
- showItem("Available for appointment:", (model.serviceItems!.data![index].isAllowAppointment ?? false) ? "Yes" : "No", valueColor: Colors.green),
- showItem("Allowing Workshop service:", (model.serviceItems!.data![index].isAppointmentCompanyLoc ?? false) ? "Yes" : "No", valueColor: Colors.green),
- showItem("Allowing home service:", (model.serviceItems!.data![index].isAppointmentCustomerLoc ?? false) ? "Yes" : "No", valueColor: Colors.green),
- 12.height,
- "Service Amount".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
- Row(
- crossAxisAlignment: CrossAxisAlignment.end,
- children: [
- model.serviceItems!.data![index].price!.toText(fontSize: 22, isBold: true),
- 2.width,
- Padding(
- padding: const EdgeInsets.only(bottom: 4),
- child: "SAR".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
- ),
- ],
+ serviceItemModel.price!.toText(fontSize: 22, isBold: true),
+ 2.width,
+ Padding(
+ padding: const EdgeInsets.only(bottom: 4),
+ child: "SAR".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
),
],
),
- ),
- // Padding(
- // padding: const EdgeInsets.all(4.0),
- // child: SvgPicture.asset(
- // MyAssets.icEdit,
- // width: 16,
- // height: 16,
- // ),
- // )
- ],
+ ],
+ ),
),
- ).toWhiteContainer(
- width: double.infinity,
- allPading: 12,
- );
- },
- separatorBuilder: (BuildContext context, int index) {
- return 12.height;
- },
- padding: const EdgeInsets.all(20),
- itemCount: model.serviceItems!.data!.length,
- );
+ // Padding(
+ // padding: const EdgeInsets.all(4.0),
+ // child: SvgPicture.asset(
+ // MyAssets.icEdit,
+ // width: 16,
+ // height: 16,
+ // ),
+ // )
+ ],
+ ),
+ ).toWhiteContainer(width: double.infinity, allPading: 12);
+ },
+ separatorBuilder: (BuildContext context, int index) {
+ return 12.height;
+ },
+ padding: const EdgeInsets.all(20),
+ );
},
),
);
diff --git a/pubspec.yaml b/pubspec.yaml
index 46981f4..3c4aa16 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -36,7 +36,7 @@ dependencies:
cupertino_icons: ^1.0.2
mc_common_app:
- path: C:/Users/mirza.shafique/AndroidStudioProjects/mc_common_app
+ path: /Volumes/Data/Projects/Flutter/car_common_app
dev_dependencies:
flutter_test:
@@ -74,7 +74,7 @@ flutter:
# To add custom fonts to your application, add a fonts section here,
# in this "flutter" section. Each entry in this list should have a
- # "family" key with the font family name, and a "fonts" key with a
+ # "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For
# example:
# fonts: