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

# Conflicts:
#	pubspec.lock
#	pubspec.yaml
aamir_dev
FaizHashmiCS22 2 years ago
commit 73fbc6c58a

@ -6,7 +6,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:7.4.2'
classpath 'com.android.tools.build:gradle:7.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

@ -0,0 +1,14 @@
## For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#Wed Dec 13 16:00:22 AST 2023
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"

@ -0,0 +1,44 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '11.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end

@ -1,14 +1,19 @@
import 'package:car_provider_app/views/appoinments/add_new_service_appointment_page.dart';
import 'package:car_provider_app/views/appoinments/appoinment_detail_list_page.dart';
import 'package:car_provider_app/views/appoinments/appointment_page.dart';
import 'package:car_provider_app/views/appoinments/merge_appointment_page.dart';
import 'package:car_provider_app/views/appoinments/update_appointment_page.dart';
import 'package:car_provider_app/views/dashboard/dashboard_page.dart';
import 'package:car_provider_app/views/requests/request_detail_page.dart';
import 'package:car_provider_app/views/requests/send_offer_page.dart';
import 'package:car_provider_app/views/settings/branch/branch_detail_page.dart';
import 'package:car_provider_app/views/settings/branch/branch_list_page.dart';
import 'package:car_provider_app/views/settings/branch/dealer/dealer_user_page.dart';
import 'package:car_provider_app/views/settings/branch/define_branch_page.dart';
import 'package:car_provider_app/views/settings/create_services_page.dart';
import 'package:car_provider_app/views/settings/schedule/add_schedules_page.dart';
import 'package:car_provider_app/views/settings/schedule/schedules_list_page.dart';
import 'package:car_provider_app/views/settings/services/create_item_page.dart';
import 'package:car_provider_app/views/settings/services/create_services_page2.dart';
import 'package:car_provider_app/views/settings/dealership_page.dart';
import 'package:car_provider_app/views/settings/define_license_page.dart';
import 'package:car_provider_app/views/settings/services/create_services_page3.dart';
@ -20,12 +25,16 @@ import 'package:car_provider_app/views/subscriptions/my_subscritions_page.dart';
import 'package:car_provider_app/views/subscriptions/subscriptions_page.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.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/chat/chat_view.dart';
import '../views/dashboard/dashboard_page.dart';
class ProviderAppRoutes {
//settings
static const defineLicense = "/defineLicese";
@ -35,8 +44,15 @@ class ProviderAppRoutes {
static const String defineBranch = "/defineBranch";
//Appointments
static const String appointment = "/appointment";
static const String appointmentDetailList = "/appointmentDetailList";
static const String updateAppointmentPage = "/updateAppointmentPage";
static const String addServiceInAppointment = "/addServiceInAppointment";
static const String mergeAppointments = "/mergeAppointments";
//Requests
static const String requestsDetailPage = "/requestsDetailPage";
static const String sendOfferPage = "/sendOfferPage";
//Services
static const String dealerUser = "/dealerUser";
@ -64,12 +80,23 @@ class ProviderAppRoutes {
defineLicense: (context) => DefineLicensePage(),
dealershipSetting: (context) => DealershipPage(),
// branchList: (context) => BranchListPage(),
defineBranch: (context) => DefineBranchPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as BranchDetailModel)),
branchDetail: (context) => BranchDetailPage(ModalRoute.of(context)!.settings.arguments as BranchDetailModel),
defineBranch: (context) => DefineBranchPage(
(ModalRoute.of(context)!.settings.arguments) == null
? null
: (ModalRoute.of(context)!.settings.arguments
as BranchDetailModel)),
branchDetail: (context) => BranchDetailPage(
ModalRoute.of(context)!.settings.arguments as BranchDetailModel),
//Appointments
appointmentDetailList: (context) => const AppointmentDetailListPage(),
updateAppointmentPage: (context) => const UpdateAppointmentPage(),
appointment: (context) => AppointmentPage(
branch:
ModalRoute.of(context)!.settings.arguments as BranchDetailModel),
appointmentDetailList: (context) => AppointmentDetailListPage(),
updateAppointmentPage: (context) => UpdateAppointmentPage(),
addServiceInAppointment: (context) => AddNewServiceAppointmentPage(
ModalRoute.of(context)!.settings.arguments as AppointmentListModel),
mergeAppointments: (context) => MergeAppointmentListPage(),
//Requests
AppRoutes.requestsDetailPage: (context) => RequestDetailPage(
@ -82,16 +109,24 @@ class ProviderAppRoutes {
AppRoutes.subscriptionsPage: (context) => const SubscriptionsPage(),
//Services
dealerUser: (context) => DealerUserPage(ModalRoute.of(context)!.settings.arguments as String),
dealerUser: (context) =>
DealerUserPage(ModalRoute.of(context)!.settings.arguments as String),
servicesList: (context) => const ServicesListPage(),
itemsList: (context) => ItemsListPage(),
createItem: (context) => const CreateItemPage(),
//createServices: (context) => CreateServicesPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as ServiceProviderBranch)),
//createServices2: (context) => CreateServicesPage2((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as ServiceProviderBranch)),
createServices3: (context) => CreateServicesPage3((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as CreateBranchModel)),
createServices3: (context) => CreateServicesPage3(
(ModalRoute.of(context)!.settings.arguments) == null
? null
: (ModalRoute.of(context)!.settings.arguments
as CreateBranchModel)),
//Schedules
schedulesList: (context) => SchedulesListPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as String)),
schedulesList: (context) => SchedulesListPage(
(ModalRoute.of(context)!.settings.arguments) == null
? null
: (ModalRoute.of(context)!.settings.arguments as String)),
addSchedule: (context) => AddSchedulesPage(),
//Branch Duplication

@ -3,6 +3,7 @@ import 'package:car_provider_app/repositories/branch_repo.dart';
import 'package:car_provider_app/repositories/items_repo.dart';
import 'package:car_provider_app/repositories/schedule_repo.dart';
import 'package:car_provider_app/repositories/subscription_repo.dart';
import 'package:car_provider_app/view_models/branch_view_model.dart';
import 'package:car_provider_app/view_models/dashboard_view_model.dart';
import 'package:car_provider_app/view_models/items_view_model.dart';
import 'package:car_provider_app/view_models/schedule_view_model.dart';
@ -11,6 +12,7 @@ import 'package:car_provider_app/view_models/subscriptions_view_model.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/models/general_models/post_params_model.dart';

@ -1,4 +1,8 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
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';
@ -6,17 +10,26 @@ import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/provider_branches_models/provider_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/branch.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/document.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/services.dart';
import 'package:mc_common_app/models/provider_branches_models/provider_model.dart';
abstract class BranchRepo {
Future<MResponse> createBranch(String branchName, String branchDescription, String cityId, String address, String latitude, String longitude);
Future<MResponse> updateBranch(int id, String branchName, String branchDescription, String cityId, String address, String latitude, String longitude, {bool isNeedToDelete = true});
Future<MResponse> createBranch(String branchName, String branchDescription,
String cityId, String address, String latitude, String longitude);
Future<MResponse> updateBranch(
int id,
String branchName,
String branchDescription,
String cityId,
String address,
String latitude,
String longitude,
{bool isNeedToDelete = true});
Future<Branch> fetchAllBranches();
@ -24,11 +37,14 @@ abstract class BranchRepo {
Future<Services> fetchServicesByCategoryId(String serviceCategoryId);
Future<Services> fetchProviderServices(String branchID, String serviceCategoryId);
Future<MResponse> createNewService(List<Map<String, dynamic>> map);
Future<Document> getServiceProviderDocument(dynamic userId);
Future<MResponse> serviceProviderDocumentsUpdate(List<DocumentData>? documents);
Future<MResponse> serviceProviderDocumentsUpdate(
List<DocumentData>? documents);
Future<ProviderModel> getBranchAndServices();
@ -36,7 +52,8 @@ abstract class BranchRepo {
Future<MResponse> updateService(List<Map<String, dynamic>> map);
Future<MResponse> getMatchedServices(int oldBranchId, int newBranchId, int categoryId);
Future<MResponse> getMatchedServices(
int oldBranchId, int newBranchId, int categoryId);
Future<MResponse> duplicateItems(Map<String, dynamic> map);
@ -47,11 +64,14 @@ abstract class BranchRepo {
Future<MResponse> assignDealerToBranch(Map<String, dynamic> map);
Future<MResponse> removeDealerFromBranch(Map<String, dynamic> map);
Future<MResponse> addNewServicesInAppointment(Map<String, dynamic> map);
}
class BranchRepoImp implements BranchRepo {
@override
Future<MResponse> createBranch(String branchName, String branchDescription, String cityId, String address, String latitude, String longitude) async {
Future<MResponse> createBranch(String branchName, String branchDescription,
String cityId, String address, String latitude, String longitude) async {
var postParams = {
"serviceProviderID": AppState().getUser.data?.userInfo?.providerId ?? "",
"branchName": branchName,
@ -64,23 +84,37 @@ class BranchRepoImp implements BranchRepo {
};
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createProviderBranch, postParams, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json),
ApiConsts.createProviderBranch,
postParams,
token: t);
}
@override
Future<Branch> fetchAllBranches() async {
var postParams = {"ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""};
var postParams = {
"ServiceProviderID":
AppState().getUser.data?.userInfo?.providerId.toString() ?? ""
};
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
return await injector.get<ApiClient>().getJsonForObject((json) => Branch.fromJson(json), ApiConsts.ServiceProviderBranchGet, queryParameters: postParams, token: t);
return await injector.get<ApiClient>().getJsonForObject(
(json) => Branch.fromJson(json), ApiConsts.ServiceProviderBranchGet,
queryParameters: postParams, token: t);
}
@override
Future<Category> fetchBranchCategory() async {
var postParams = {"ServiceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""};
var postParams = {
"ServiceProviderID":
AppState().getUser.data?.userInfo?.providerId.toString() ?? ""
};
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
return await injector.get<ApiClient>().getJsonForObject((json) => Category.fromJson(json), ApiConsts.ServiceCategory_Get, queryParameters: postParams, token: t);
return await injector.get<ApiClient>().getJsonForObject(
(json) => Category.fromJson(json), ApiConsts.ServiceCategory_Get,
queryParameters: postParams, token: t);
}
@override
@ -88,13 +122,19 @@ class BranchRepoImp implements BranchRepo {
var postParams = {"ServiceCategoryID": serviceCategoryId};
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
return await injector.get<ApiClient>().getJsonForObject((json) => Services.fromJson(json), ApiConsts.Services_Get, queryParameters: postParams, token: t);
return await injector.get<ApiClient>().getJsonForObject(
(json) => Services.fromJson(json), ApiConsts.Services_Get,
queryParameters: postParams, token: t);
}
@override
Future<MResponse> createNewService(List<Map<String, dynamic>> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Create, map, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json),
ApiConsts.ServiceProviderService_Create,
map,
token: t);
}
@override
@ -104,13 +144,15 @@ class BranchRepoImp implements BranchRepo {
};
String? token = AppState().getUser.data?.accessToken;
debugPrint(token);
return await injector
.get<ApiClient>()
.getJsonForObject((json) => Document.fromJson(json), ApiConsts.GetProviderDocument, queryParameters: queryParameters, token: AppState().getUser.data!.accessToken ?? "");
return await injector.get<ApiClient>().getJsonForObject(
(json) => Document.fromJson(json), ApiConsts.GetProviderDocument,
queryParameters: queryParameters,
token: AppState().getUser.data!.accessToken ?? "");
}
@override
Future<MResponse> serviceProviderDocumentsUpdate(List<DocumentData>? documents) async {
Future<MResponse> serviceProviderDocumentsUpdate(
List<DocumentData>? documents) async {
List<Map<String, dynamic>> map = [];
for (int i = 0; i < documents!.length; i++) {
if (documents[i].document != null) {
@ -127,19 +169,36 @@ class BranchRepoImp implements BranchRepo {
}
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderDocument_Update, map, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json),
ApiConsts.ServiceProviderDocument_Update,
map,
token: t);
}
@override
Future<ProviderModel> getBranchAndServices() async {
var postParams = {"serviceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""};
var postParams = {
"serviceProviderID":
AppState().getUser.data?.userInfo?.providerId.toString() ?? ""
};
String t = AppState().getUser.data!.accessToken ?? "";
print("tokeen121 " + t);
return await injector.get<ApiClient>().getJsonForObject((json) => ProviderModel.fromJson(json), ApiConsts.BranchesAndServices, queryParameters: postParams, token: t);
return await injector.get<ApiClient>().getJsonForObject(
(json) => ProviderModel.fromJson(json), ApiConsts.BranchesAndServices,
queryParameters: postParams, token: t);
}
@override
Future<MResponse> updateBranch(int id, String branchName, String branchDescription, String cityId, String address, String latitude, String longitude, {bool isNeedToDelete = true}) async {
Future<MResponse> updateBranch(
int id,
String branchName,
String branchDescription,
String cityId,
String address,
String latitude,
String longitude,
{bool isNeedToDelete = true}) async {
String lat = "0", long = "0";
try {
lat = latitude.substring(0, 9);
@ -157,59 +216,109 @@ class BranchRepoImp implements BranchRepo {
"isActive": isNeedToDelete
};
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateProviderBranch, postParams, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json),
ApiConsts.updateProviderBranch,
postParams,
token: t);
}
@override
Future<MResponse> createService(List<Map<String, dynamic>> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Create, map, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json),
ApiConsts.ServiceProviderService_Create,
map,
token: t);
}
@override
Future<MResponse> updateService(List<Map<String, dynamic>> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.ServiceProviderService_Update, map, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json),
ApiConsts.ServiceProviderService_Update,
map,
token: t);
}
@override
Future<MResponse> getMatchedServices(int oldBranchId, int newBranchId, int categoryId) async {
Future<MResponse> getMatchedServices(
int oldBranchId, int newBranchId, int categoryId) async {
var postParams = {
"ProviderBranchIDExisted": oldBranchId.toString(),
"ProviderBranchIDNew": newBranchId.toString(),
"CategoryID": categoryId.toString(),
};
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getMatchedServices, queryParameters: postParams, token: t);
return await injector.get<ApiClient>().getJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.getMatchedServices,
queryParameters: postParams, token: t);
}
@override
Future<MResponse> duplicateItems(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.duplicateItems, map, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.duplicateItems, map,
token: t);
}
@override
Future<MResponse> getAllProviderDealers(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getAllProviderDealers, queryParameters: map, token: t);
return await injector.get<ApiClient>().getJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.getAllProviderDealers,
queryParameters: map, token: t);
}
@override
Future<MResponse> getBranchUsers(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().getJsonForObject((json) => MResponse.fromJson(json), ApiConsts.getBranchUser, queryParameters: map, token: t);
return await injector.get<ApiClient>().getJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.getBranchUser,
queryParameters: map, token: t);
}
@override
Future<MResponse> assignDealerToBranch(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.assignDealerToBranch, map, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json), ApiConsts.assignDealerToBranch, map,
token: t);
}
@override
Future<MResponse> removeDealerFromBranch(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.removeDealerFromBranch, map, token: t);
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json),
ApiConsts.removeDealerFromBranch,
map,
token: t);
}
@override
Future<Services> fetchProviderServices(String branchID, String serviceCategoryId) async {
var postParams = {
"ServiceCategoryID": serviceCategoryId,
"ProviderBranchID": branchID,
};
String t = AppState().getUser.data!.accessToken ?? "";
debugPrint("token " + t);
return await injector.get<ApiClient>().getJsonForObject(
(json) => Services.fromJson(json), ApiConsts.GetProviderServices,
queryParameters: postParams, token: t);
}
@override
Future<MResponse> addNewServicesInAppointment(Map<String, dynamic> map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject(
(json) => MResponse.fromJson(json),
ApiConsts.AddNewServicesInAppointment,
map,
token: t);
}
}

@ -7,6 +7,7 @@ import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
abstract class ItemsRepo {
Future<MResponse> createServiceItems(Map map);

@ -4,6 +4,8 @@ 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/subscriptions_models/subscription_model.dart';
import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart';
abstract class SubscriptionRepo {
Future<SubscriptionModel> getAllSubscriptions(String? serviceProviderID);

@ -9,6 +9,8 @@ import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
import 'package:file_picker/file_picker.dart';
import '../views/settings/schedule/widgets/chips_picker_item.dart';
class ItemsVM extends BaseVM {
final ItemsRepo itemsRepo;
final CommonAppServices commonServices;
@ -40,9 +42,25 @@ class ItemsVM extends BaseVM {
return response;
}
Future<ItemModel?> getServiceItems(int serviceId) async {
Future<ItemModel?> getServiceItems(int serviceId,
{List<PickerItem>? list}) async {
serviceItems = null;
setOnlyState(ViewState.busy);
serviceItems = await itemsRepo.getServiceItems(serviceId);
if (list != null) {
for (var element in list) {
for (var innerElement in serviceItems!.data!) {
if (element.id == innerElement.id) {
innerElement.isUpdateOrSelected = true;
}
}
// serviceItems!.data!.where(
// (innerElement) => element.id == innerElement.id
// ? innerElement.isUpdateOrSelected = true
// : innerElement.isUpdateOrSelected = true,
// );
}
}
setState(ViewState.idle);
return serviceItems;
}

@ -235,18 +235,22 @@
// }
// }
import 'dart:convert';
import 'dart:io';
import 'package:car_provider_app/repositories/branch_repo.dart';
import 'package:file_picker/file_picker.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/provider_branches_models/provider_model.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/document.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/services.dart';
import 'package:mc_common_app/models/provider_branches_models/provider_model.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/models/services_models/service_model.dart';
import 'package:mc_common_app/models/user_models/branch_user.dart';
import 'package:mc_common_app/models/user_models/cities.dart';
import 'package:mc_common_app/models/user_models/country.dart';
import 'package:mc_common_app/repositories/common_repo.dart';
@ -342,7 +346,8 @@ class ServiceVM extends BaseVM {
setState(ViewState.idle);
}
Future<void> getAllCountriesList(BranchDetailModel? branchData, String countryCode) async {
Future<void> getAllCountriesList(
BranchDetailModel? branchData, String countryCode) async {
setState(ViewState.busy);
resetValues();
country = await commonRepo.getAllCountries();
@ -351,7 +356,9 @@ class ServiceVM extends BaseVM {
if (element.id == branchData.countryID) {
countryValue = DropValue(
element.id ?? 0,
countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""),
countryCode == "SA"
? (element.countryNameN ?? "")
: (element.countryName ?? ""),
element.countryCode ?? "",
);
}
@ -359,7 +366,9 @@ class ServiceVM extends BaseVM {
countryDropList.add(
DropValue(
element.id ?? 0,
countryCode == "SA" ? (element.countryNameN ?? "") : (element.countryName ?? ""),
countryCode == "SA"
? (element.countryNameN ?? "")
: (element.countryName ?? ""),
element.countryCode ?? "",
),
);
@ -370,7 +379,8 @@ class ServiceVM extends BaseVM {
setState(ViewState.idle);
}
Future<void> getAllCities(BranchDetailModel? branchData, String countryCode) async {
Future<void> getAllCities(
BranchDetailModel? branchData, String countryCode) async {
setState(ViewState.busy);
citiesDropList.clear();
cities = null;
@ -388,7 +398,9 @@ class ServiceVM extends BaseVM {
cityId = branchData.cityId!;
cityValue = DropValue(
element.id ?? 0,
countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""),
countryCode == "SA"
? (element.cityNameN ?? "")
: (element.cityName ?? ""),
element.id.toString() ?? "",
);
}
@ -396,7 +408,9 @@ class ServiceVM extends BaseVM {
citiesDropList.add(
DropValue(
element.id ?? 0,
countryCode == "SA" ? (element.cityNameN ?? "") : (element.cityName ?? ""),
countryCode == "SA"
? (element.cityNameN ?? "")
: (element.cityName ?? ""),
element.id.toString() ?? "",
),
);
@ -404,8 +418,10 @@ class ServiceVM extends BaseVM {
setState(ViewState.idle);
}
Future<MResponse> createBranch(String branchName, String branchDescription, String cityId, String address, String latitude, String longitude) async {
return await branchRepo.createBranch(branchName, branchDescription, cityId.toString(), address, latitude.toString(), longitude.toString());
Future<MResponse> createBranch(String branchName, String branchDescription,
String cityId, String address, String latitude, String longitude) async {
return await branchRepo.createBranch(branchName, branchDescription,
cityId.toString(), address, latitude.toString(), longitude.toString());
}
Future<MResponse> updateBranch(
@ -493,6 +509,24 @@ class ServiceVM extends BaseVM {
setState(ViewState.idle);
}
Future<void> fetchProviderServices(String branchID, String categoryId) async {
servicesDropList = [];
services=null;
setState(ViewState.busy);
services = await branchRepo.fetchProviderServices(branchID, categoryId);
for (var element in services!.data!) {
servicesDropList.add(
DropValue(
element.id ?? 0,
element.description ?? "N/A",
"",
),
);
}
setState(ViewState.idle);
}
Future<MResponse> createService(List<Map<String, dynamic>> map) async {
return await branchRepo.createService(map);
}
@ -509,13 +543,16 @@ class ServiceVM extends BaseVM {
List<ServiceModel>? matchedServices;
bool isAllSelected = false;
Future<void> getAllMatchedServices(int oldBranchId, int newBranchId, int categoryId) async {
Future<void> getAllMatchedServices(
int oldBranchId, int newBranchId, int categoryId) async {
matchedServices = null;
final MResponse response = await branchRepo.getMatchedServices(oldBranchId, newBranchId, categoryId);
final MResponse response = await branchRepo.getMatchedServices(
oldBranchId, newBranchId, categoryId);
matchedServices = [];
if (response.messageStatus == 1) {
matchedServices = List<ServiceModel>.from(response.data.map((x) => ServiceModel.fromJson(x)));
matchedServices = List<ServiceModel>.from(
response.data.map((x) => ServiceModel.fromJson(x)));
}
notifyListeners();
}
@ -555,8 +592,9 @@ class ServiceVM extends BaseVM {
setState(ViewState.busy);
MResponse response = await branchRepo.getAllProviderDealers(map);
if (response.messageStatus == 1) {
allProviderDealersList=[];
allProviderDealersList = List<BranchUser>.from(response.data.map((x) => BranchUser.fromJson(x)));
allProviderDealersList = [];
allProviderDealersList = List<BranchUser>.from(
response.data.map((x) => BranchUser.fromJson(x)));
}
setState(ViewState.idle);
}
@ -565,8 +603,9 @@ class ServiceVM extends BaseVM {
setState(ViewState.busy);
MResponse response = await branchRepo.getBranchUsers(map);
if (response.messageStatus == 1) {
branchUserList=[];
branchUserList = List<BranchUser>.from(response.data.map((x) => BranchUser.fromJson(x)));
branchUserList = [];
branchUserList = List<BranchUser>.from(
response.data.map((x) => BranchUser.fromJson(x)));
}
setState(ViewState.idle);
}
@ -580,4 +619,9 @@ class ServiceVM extends BaseVM {
MResponse response = await branchRepo.removeDealerFromBranch(map);
return response;
}
Future<MResponse> addNewServiceInAppointment(Map<String, dynamic> map) async {
MResponse response = await branchRepo.addNewServicesInAppointment(map);
return response;
}
}

@ -0,0 +1,286 @@
import 'package:car_provider_app/view_models/service_view_model.dart';
import 'package:car_provider_app/views/appoinments/widget/select_items_sheet.dart';
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/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.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/dropdown/dropdow_field.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart';
import '../../generated/locale_keys.g.dart';
import '../dashboard/widget/appointment_slider_widget.dart';
import '../settings/schedule/widgets/chips_picker_item.dart';
class AddNewServiceAppointmentPage extends StatelessWidget {
AppointmentListModel appointmentListModel;
AddNewServiceAppointmentPage(this.appointmentListModel, {Key? key})
: super(key: key);
DropValue? category;
DropValue? service;
List<ItemData> selectedList = [];
List<PickerItem>? pickedItems;
@override
Widget build(BuildContext context) {
ServiceVM serviceVM = context.read<ServiceVM>();
serviceVM.fetchBranchCategory(
EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
return Scaffold(
appBar: const CustomAppBar(
title: "Add Service",
),
body: Padding(
padding: const EdgeInsets.all(21.0),
child: Column(
children: [
AppointmentSliderWidget(
appointmentListModel: appointmentListModel,
isNeedTotalPayment: true,
isNeedToShowItems: true,
isNeedToShowToMoreText: false,
onTap: () {},
),
12.height,
Expanded(
child: Consumer<ServiceVM>(
builder: (context, model, _) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Select services you want to add".toText(
fontSize: 18,
isBold: true,
),
12.height,
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
model.categoryDropList.isNotEmpty
? DropdownField(
(DropValue value) async {
category = value;
service = null;
model.fetchProviderServices(
appointmentListModel.branchId
.toString(),
value.id.toString());
},
dropdownValue: category,
list: model.categoryDropList,
hint:
LocaleKeys.selectServiceCategory.tr(),
)
: const Center(
child: CircularProgressIndicator(),
),
12.height,
model.servicesDropList.isNotEmpty
? DropdownField(
(DropValue value) {
service = value;
pickedItems = null;
model.setState(ViewState.idle);
showMyBottomSheet(
context,
child: SelectItemsSheet(
serviceId: service?.id ?? 0,
onSelectItems:
(List<ItemData> selectedList) {
this.selectedList.clear();
this.selectedList = selectedList;
pickedItems = [];
for (var element
in selectedList) {
pickedItems!.add(
PickerItem(
id: element.id ?? 0,
title:
element.name ?? ""),
);
}
model.notifyListeners();
},
),
);
},
dropdownValue: service,
list: model.servicesDropList,
hint: LocaleKeys.defineServices.tr(),
)
: category == null
? Container()
: model.services != null &&
model.servicesDropList.isEmpty
? const Text("No Service Found")
: const CircularProgressIndicator(),
12.height,
(service != null &&
pickedItems != null &&
pickedItems!.length > 0)
? ChipsPickerItem(
hint: 'Select Items',
itemsList: [...pickedItems ?? []],
onClick: () {
showMyBottomSheet(
context,
child: SelectItemsSheet(
serviceId: service?.id ?? 0,
list: pickedItems,
onSelectItems:
(List<ItemData> selectedList) {
pickedItems = [];
for (var element
in selectedList) {
pickedItems!.add(
PickerItem(
id: element.id ?? 0,
title:
element.name ?? ""),
);
}
model.notifyListeners();
},
),
);
},
)
: service != null
? const Text("No Item Selected Yet")
: const SizedBox(),
if ((service != null &&
pickedItems != null &&
pickedItems!.length > 0))
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
16.height,
"Total Additional Amount".toText(
fontSize: 14,
isBold: true,
color: MyColors.lightTextColor,
),
Row(
crossAxisAlignment:
CrossAxisAlignment.end,
children: [
calculatePrice().toString().toText(
fontSize: 29,
isBold: true,
),
2.width,
"SAR".toText(
fontSize: 16,
isBold: true,
color: MyColors.lightTextColor,
),
],
),
],
),
],
),
],
).toWhiteContainer(width: double.infinity, allPading: 12),
Row(
children: [
Expanded(
child: ShowFillButton(
title: "Cancel",
maxWidth: double.infinity,
isFilled: false,
txtColor: MyColors.redColor,
borderColor: MyColors.redColor,
onPressed: () {},
),
),
12.width,
Expanded(
child: ShowFillButton(
title: "Add",
maxWidth: double.infinity,
onPressed: () async {
if (pickedItems != null &&
pickedItems!.length > 0) {
List<int> items = [];
pickedItems?.forEach((element) {
items.add(element.id);
});
Utils.showLoading(context);
var postParams = {
"providerBranchID":
appointmentListModel.branchId,
"appointmentID": appointmentListModel.id,
"serviceItemID": items
};
MResponse res = await serviceVM
.addNewServiceInAppointment(postParams);
_updateAppointment(context,
appointmentListModel.branchId ?? 0);
Utils.hideLoading(context);
if (res.messageStatus == 1) {
Utils.showToast(
"Items are added Successfully");
pop(context);
} else {
Utils.showToast(res.message.toString());
}
} else {
Utils.showToast("Please select items");
}
},
),
),
],
),
],
);
},
),
),
],
),
),
);
}
Future<void> _updateAppointment(BuildContext context, int branchId) async {
await context.read<AppointmentsVM>().getProviderMyAppointments({
"ServiceProviderID": injector
.get<AppState>()
.getUser
.data
?.userInfo
?.providerId
.toString() ??
"0",
"ProviderBranchID": branchId.toString(),
}, isNeedToRebuild: true);
}
double calculatePrice() {
double total = 0;
for (var element in selectedList) {
total = total + double.parse(element.price ?? "0");
}
return total;
}
}

@ -1,11 +1,18 @@
import 'package:car_provider_app/views/appoinments/widget/appointment_detail_list_widget.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import '../../config/provider_routes.dart';
import '../dashboard/widget/appointment_slider_widget.dart';
import 'package:provider/provider.dart';
class AppointmentDetailListPage extends StatelessWidget {
const AppointmentDetailListPage({Key? key}) : super(key: key);
AppointmentDetailListPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -19,20 +26,60 @@ class AppointmentDetailListPage extends StatelessWidget {
child: Column(
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.all(21),
children: [
AppointmentDetailListWidget(),
21.height,
AppointmentDetailListWidget(),
],
),
child: Consumer(builder: (BuildContext context,
AppointmentsVM appointmentsVM, Widget? child) {
if (appointmentsVM.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
return ListView.separated(
itemBuilder: (context, index) {
return AppointmentSliderWidget(
appointmentListModel: appointmentsVM
.myFilteredAppointments2[
appointmentsVM.selectedAppointmentIndex]
.customerAppointmentList![index],
isNeedTotalPayment: true,
isNeedToShowAppointmentStatus: true,
isNeedToShowMergeStatus: true,
onTap: () {
appointmentsVM.selectedAppointmentId =
appointmentsVM
.myFilteredAppointments2[appointmentsVM
.selectedAppointmentIndex]
.customerAppointmentList![index]
.id ??
0;
appointmentsVM.selectedAppointmentSubIndex = index;
navigateWithName(context,
ProviderAppRoutes.updateAppointmentPage,
arguments: appointmentsVM
.myFilteredAppointments2[
appointmentsVM.selectedAppointmentIndex]
.customerAppointmentList![index]);
},
);
},
separatorBuilder: (context, snapchat) {
return 21.height;
},
itemCount: appointmentsVM
.myFilteredAppointments2[
appointmentsVM.selectedAppointmentIndex]
.customerAppointmentList!
.length,
padding: const EdgeInsets.all(21),
);
}
}),
),
ShowFillButton(
title: "Merge Appointments",
maxWidth: double.infinity,
margin: const EdgeInsets.all(21),
onPressed: () {},
onPressed: () {
navigateWithName(
context, ProviderAppRoutes.mergeAppointments);
},
),
],
)),

@ -0,0 +1,273 @@
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:car_provider_app/views/dashboard/widget/appointment_slider_widget.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/extensions/string_extensions.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/date_helper.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/common_widgets/categories_list.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.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/widgets/common_widgets/app_bar.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'package:provider/provider.dart';
class AppointmentPage extends StatelessWidget {
BranchDetailModel branch;
String date = "";
AppointmentPage({
required this.branch,
Key? key,
}) : super(key: key);
GlobalKey<RefreshIndicatorState> refreshIndicatorKey =
GlobalKey<RefreshIndicatorState>();
Future<void> _pullRefresh(BuildContext context) async {
await context.read<AppointmentsVM>().getAppointmentSlotsInfo(
context: context,
map: {
"ProviderBranchID": branch.id.toString(),
"FromDate": date,
"ToDate": date
},
isNeedToRebuild: true,
);
await context.read<AppointmentsVM>().getProviderMyAppointments({
"ServiceProviderID": injector
.get<AppState>()
.getUser
.data
?.userInfo
?.providerId
.toString() ??
"0",
"ProviderBranchID": branch.id.toString(),
"FromDate": date,
"DateTo": date,
});
}
@override
Widget build(BuildContext context) {
date = DateHelper.formatAsYearMonthDay(DateTime.now());
context.read<AppointmentsVM>().setupProviderAppointmentFilter();
_pullRefresh(context);
context.read<AppointmentsVM>().selectedBranch = branch.id ?? 0;
return Scaffold(
appBar: CustomAppBar(
profileImageUrl: MyAssets.carBanner,
title: branch.branchName,
),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Consumer(builder: (BuildContext context,
AppointmentsVM appointmentsVM, Widget? child) {
if (appointmentsVM.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
return RefreshIndicator(
onRefresh: () => _pullRefresh(context),
key: refreshIndicatorKey,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
children: [
progressWidget(context, appointmentsVM),
FiltersList(
filterList: appointmentsVM.appointmentsFilterOptions,
padding: const EdgeInsets.symmetric(horizontal: 18),
onFilterTapped: (index, selectedFilterId) {
appointmentsVM.applyFilterOnAppointmentsVM(
appointmentStatusEnum:
selectedFilterId.toAppointmentStatusEnum(),
isNeedCustomerFilter: true,
);
},
),
if (appointmentsVM.myFilteredAppointments2.isEmpty)
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: "No Appointment Found".toText(),
),
ListView.separated(
itemBuilder: (context, index) {
return AppointmentSliderWidget(
appointmentListModel:
appointmentsVM.myFilteredAppointments2[index],
isNeedTotalPayment: false,
onTap: () {
context
.read<AppointmentsVM>()
.selectedAppointmentIndex = index;
navigateWithName(
context,
ProviderAppRoutes.appointmentDetailList,
// arguments: appointmentsVM
// .myFilteredAppointments2[index]
// .customerAppointmentList,
);
},
);
},
separatorBuilder: (context, snapchat) {
return 21.height;
},
itemCount: appointmentsVM.myFilteredAppointments2.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: const EdgeInsets.all(21),
),
],
),
),
);
}
}),
),
);
}
Widget progressWidget(BuildContext context, AppointmentsVM appointmentsVM) {
double percent = (appointmentsVM.appointmentSlots?.occupiedSlots ??
0.0 / (appointmentsVM.appointmentSlots?.totalSlots ?? 0.0))
.toDouble() *
100;
return Column(
children: [
Row(
children: [
Expanded(
child: "Slots Overview".toText(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Row(
children: [
date.toText(
fontWeight: FontWeight.bold,
),
const Icon(
Icons.keyboard_arrow_down_outlined,
size: 16,
),
],
)
.toContainer(
backgroundColor: MyColors.lightGreyEAColor,
borderRadius: 100,
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
),
)
.onPress(() async {
date = await Utils.pickDateFromDatePicker(
context,
firstDate: null,
);
_pullRefresh(context);
// context.read<AppointmentsVM>().notifyListeners();
}),
],
),
24.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 14,
height: 14,
color: MyColors.lightGreyEAColor,
),
4.width,
"Empty: ".toText(
fontSize: 8,
color: Colors.white,
),
(appointmentsVM.appointmentSlots?.emptySlots ?? 0)
.toString()
.toText(
fontSize: 9,
fontWeight: FontWeight.bold,
color: Colors.white,
),
],
).toContainer(
backgroundColor: MyColors.darkIconColor,
),
8.height,
Row(
children: [
Container(
width: 14,
height: 14,
color: MyColors.darkPrimaryColor,
),
4.width,
"Occupied: ".toText(
fontSize: 8,
color: Colors.white,
),
(appointmentsVM.appointmentSlots?.occupiedSlots ?? 0)
.toString()
.toText(
fontSize: 9,
fontWeight: FontWeight.bold,
color: Colors.white,
),
],
).toContainer(
backgroundColor: MyColors.darkIconColor,
),
],
),
CircularPercentIndicator(
radius: 60.0,
lineWidth: 12.0,
percent: percent,
circularStrokeCap: CircularStrokeCap.round,
center: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
"Total Slots".toText(
fontSize: 13,
fontWeight: FontWeight.bold,
),
(appointmentsVM.appointmentSlots?.totalSlots ?? 0)
.toString()
.toText(
fontSize: 24,
fontWeight: FontWeight.bold,
),
],
),
backgroundColor: MyColors.lightGreyEAColor,
progressColor: MyColors.darkPrimaryColor,
),
],
)
],
).toWhiteContainer(
width: double.infinity,
pading: const EdgeInsets.all(12),
margin: const EdgeInsets.all(21),
);
}
}

@ -0,0 +1,159 @@
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/extensions/int_extensions.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import '../../config/provider_routes.dart';
import '../dashboard/widget/appointment_slider_widget.dart';
import 'package:provider/provider.dart';
class MergeAppointmentListPage extends StatelessWidget {
MergeAppointmentListPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: const CustomAppBar(
title: "Select Appointments",
),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Consumer(
builder: (BuildContext context, AppointmentsVM appointmentsVM,
Widget? child) {
return Column(
children: [
Expanded(
child: Column(
children: [
Expanded(
child: (appointmentsVM.state == ViewState.busy)
? const Center(child: CircularProgressIndicator())
: ListView.separated(
itemBuilder: (context, index) {
return AppointmentSliderWidget(
appointmentListModel: appointmentsVM
.myFilteredAppointments2[appointmentsVM
.selectedAppointmentIndex]
.customerAppointmentList![index],
isNeedTotalPayment: true,
isSelectable: true,
isNeedToShowAppointmentStatus: true,
isNeedToShowMergeStatus: true,
onTap: () {
appointmentsVM
.updateCheckBoxInMergeRequest(index);
},
);
},
separatorBuilder: (context, snapchat) {
return 21.height;
},
itemCount: appointmentsVM
.myFilteredAppointments2[
appointmentsVM.selectedAppointmentIndex]
.customerAppointmentList!
.length,
padding: const EdgeInsets.all(21),
),
),
],
),
),
ShowFillButton(
title: "Merge Appointments",
maxWidth: double.infinity,
margin: const EdgeInsets.all(21),
txtColor: appointmentsVM.inNeedToEnableMergeButton
? MyColors.white
: MyColors.black,
backgroundColor: appointmentsVM.inNeedToEnableMergeButton
? MyColors.primaryColor
: MyColors.greyButtonColor,
onPressed: () async {
Utils.showLoading(context);
List<int> appointmentIDs = [];
for (var element in appointmentsVM
.myFilteredAppointments2[
appointmentsVM.selectedAppointmentIndex]
.customerAppointmentList!) {
if (element.isSelected ?? false) {
appointmentIDs.add(element.id ?? 0);
}
}
Map<String, dynamic> map = {
"serviceProviderID": injector
.get<AppState>()
.getUser
.data
?.userInfo
?.providerId
.toString() ??
"0",
"serviceProviderBranchID": appointmentsVM
.myFilteredAppointments2[
appointmentsVM.selectedAppointmentIndex]
.branchId,
"serviceAppointmentIDs": appointmentIDs
};
try {
MResponse response =
await appointmentsVM.createMergeAppointment(map);
Utils.hideLoading(context);
if (response.messageStatus == 1) {
Utils.showToast(
"Appointment Merge is Successfully done");
_updateAppointment(
context,
appointmentsVM
.myFilteredAppointments2[
appointmentsVM.selectedAppointmentIndex]
.branchId ??
0);
pop(context);
pop(context);
} else {
Utils.showToast(response.message.toString());
}
} catch (e) {
Utils.showToast(e.toString());
Utils.hideLoading(context);
}
},
),
],
);
},
),
),
);
}
Future<void> _updateAppointment(BuildContext context, int branchId) async {
await context.read<AppointmentsVM>().getProviderMyAppointments({
"ServiceProviderID": injector
.get<AppState>()
.getUser
.data
?.userInfo
?.providerId
.toString() ??
"0",
"ProviderBranchID": branchId.toString(),
}, isNeedToRebuild: true);
}
}

@ -1,11 +1,28 @@
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:car_provider_app/views/appoinments/widget/appointment_detail_list_widget.dart';
import 'package:car_provider_app/views/appoinments/widget/sheets.dart';
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/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.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';
import '../dashboard/widget/appointment_slider_widget.dart';
class UpdateAppointmentPage extends StatelessWidget {
const UpdateAppointmentPage({Key? key}) : super(key: key);
late AppointmentListModel appointmentListModel;
UpdateAppointmentPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -16,42 +33,289 @@ class UpdateAppointmentPage extends StatelessWidget {
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Column(
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.all(21),
children: [
AppointmentDetailListWidget(
isNeedClick: false,
),
],
),
),
Padding(
padding: const EdgeInsets.all(21.0),
child: Row(
children: [
Expanded(
child: ShowFillButton(
title: "Cancel",
maxWidth: double.infinity,
onPressed: () {},
),
child: Consumer(builder: (BuildContext context,
AppointmentsVM appointmentsVM, Widget? child) {
appointmentListModel = appointmentsVM
.myFilteredAppointments2[
appointmentsVM.selectedAppointmentIndex]
.customerAppointmentList![
appointmentsVM.selectedAppointmentSubIndex];
if (appointmentsVM.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
return Column(
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.all(21),
children: [
AppointmentSliderWidget(
appointmentListModel: appointmentListModel,
isNeedTotalPayment: true,
isNeedToShowItems: true,
isNeedToShowToMoreText: false,
onTap: () {},
),
21.height,
ShowFillButton(
title: "+ Add New Service",
txtColor: MyColors.darkPrimaryColor,
isFilled: false,
onPressed: () {
navigateWithName(
context,
ProviderAppRoutes.addServiceInAppointment,
arguments: appointmentListModel,
);
},
),
],
),
21.width,
Expanded(
child: ShowFillButton(
title: "Merge Appointments",
maxWidth: double.infinity,
onPressed: () {},
),
),
],
),
),
],
)),
),
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.cancelled)
"Appointment is Canceled".toText(),
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.booked)
Column(
children: [
showPayNowButton(context, appointmentsVM),
21.height,
showCancelButton(context, appointmentsVM),
],
).paddingAll(21),
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.confirmed &&
appointmentListModel.appointmentPaymentStatusEnum ==
AppointmentPaymentStatusEnum.defaultStatus)
Column(
children: [
showArrivedutton(context, appointmentsVM),
],
).paddingAll(21),
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.arrived &&
appointmentListModel.appointmentPaymentStatusEnum ==
AppointmentPaymentStatusEnum.defaultStatus)
Column(
children: [
showPayNowButton(context, appointmentsVM),
21.height,
showPayLaterButton(context, appointmentsVM),
],
).paddingAll(21),
if ((appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.arrived ||
appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.workStarted) &&
appointmentListModel.appointmentPaymentStatusEnum ==
AppointmentPaymentStatusEnum.payNow)
"Waiting for the payment from the customer".toText(),
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.arrived &&
(appointmentListModel.appointmentPaymentStatusEnum ==
AppointmentPaymentStatusEnum.paid ||
appointmentListModel.appointmentPaymentStatusEnum ==
AppointmentPaymentStatusEnum.payLater))
Column(
children: [
showWorkStartButton(context, appointmentsVM),
],
).paddingAll(21),
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.workStarted &&
appointmentListModel.appointmentPaymentStatusEnum ==
AppointmentPaymentStatusEnum.payPartial)
Column(
children: [
showPayLaterButton(context, appointmentsVM),
21.height,
showPayNowButton(context, appointmentsVM),
],
).paddingAll(21),
// "Show Pay Now".toText(),
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.workStarted &&
appointmentListModel.appointmentPaymentStatusEnum ==
AppointmentPaymentStatusEnum.paid)
Column(
children: [
showCompleteButton(context, appointmentsVM),
],
).paddingAll(21),
// "Show Complete Button".toText(),
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.workStarted &&
appointmentListModel.appointmentPaymentStatusEnum ==
AppointmentPaymentStatusEnum.payLater)
showPayNowButton(context, appointmentsVM),
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.visitCompleted)
"Appointment is completed".toText().paddingAll(21),
// Padding(
// padding: const EdgeInsets.all(21.0),
// child: Column(
// children: [
// ShowFillButton(
// title: "Confirm Arrive",
// maxWidth: double.infinity,
// onPressed: () {
// showMyBottomSheet(
// context,
// child: ShowCollectPaymentSheet(
// onClickYes: () {},
// onClickNo: () {},
// ),
// );
// },
// ),
// 12.height,
// ShowFillButton(
// title: "Cancel Appointment",
// maxWidth: double.infinity,
// isFilled: false,
// txtColor: MyColors.redColor,
// borderColor: MyColors.redColor,
// onPressed: () {
// showMyBottomSheet(context,
// child: CancelAppointmentReasonSheet(
// onCancelClick: (String reason) {},
// ));
// },
// ),
// ],
// ),
// ),
],
);
}
})),
);
}
Widget showWorkStartButton(
BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: "Work Start",
maxWidth: double.infinity,
onPressed: () async {
Utils.showLoading(context);
await appointmentsVM.updateAppointmentStatus({
"appointmentID": appointmentListModel.id.toString(),
"appointmentStatusID": 7
});
Utils.hideLoading(context);
// showMyBottomSheet(
// context,
// child: ShowCollectPaymentSheet(
// onClickYes: () {},
// onClickNo: () {},
// ),
// );
},
);
}
Widget showPayNowButton(BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: "Pay Now",
maxWidth: double.infinity,
onPressed: () async {
Utils.showLoading(context);
await appointmentsVM.updateAppointmentPaymentStatus({
"appointmentID": appointmentListModel.id.toString(),
"appointmentServicePaymentStatusID": 2
});
Utils.hideLoading(context);
},
);
}
Widget showArrivedutton(BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: "Arrived",
maxWidth: double.infinity,
onPressed: () async {
Utils.showLoading(context);
await appointmentsVM.updateAppointmentStatus({
"appointmentID": appointmentListModel.id.toString(),
"appointmentStatusID": 3
});
Utils.hideLoading(context);
},
);
}
Widget showPayLaterButton(
BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: "Pay Later",
maxWidth: double.infinity,
onPressed: () async {
Utils.showLoading(context);
await appointmentsVM.updateAppointmentPaymentStatus({
"appointmentID": appointmentListModel.id.toString(),
"appointmentServicePaymentStatusID": 4
});
Utils.hideLoading(context);
},
);
}
Widget showCompleteButton(
BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: "Complete",
maxWidth: double.infinity,
onPressed: () async {
Utils.showLoading(context);
await appointmentsVM.updateAppointmentStatus({
"appointmentID": appointmentListModel.id.toString(),
"appointmentStatusID": 8
});
Utils.hideLoading(context);
},
);
}
Widget showCancelButton(BuildContext context, AppointmentsVM appointmentsVM) {
return ShowFillButton(
title: "Cancel",
maxWidth: double.infinity,
isFilled: false,
txtColor: MyColors.redColor,
borderColor: MyColors.redColor,
onPressed: () {
showMyBottomSheet(
context,
child: ShowCollectPaymentSheet(
onClickYes: () {},
onClickNo: () {},
),
);
},
);
}
Future<void> _updateAppointment(BuildContext context, int branchId) async {
await context.read<AppointmentsVM>().getProviderMyAppointments({
"ServiceProviderID": injector
.get<AppState>()
.getUser
.data
?.userInfo
?.providerId
.toString() ??
"0",
"ProviderBranchID": branchId.toString(),
}, isNeedToRebuild: true);
}
}

@ -0,0 +1,144 @@
import 'package:car_provider_app/view_models/items_view_model.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/services_models/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/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
import 'package:provider/provider.dart';
import '../../settings/schedule/widgets/chips_picker_item.dart';
class SelectItemsSheet extends StatelessWidget {
int serviceId;
Function(List<ItemData>) onSelectItems;
List<PickerItem>? list;
SelectItemsSheet(
{Key? key,
required this.serviceId,
required this.onSelectItems,
this.list})
: super(key: key);
@override
Widget build(BuildContext context) {
context.read<ItemsVM>().getServiceItems(serviceId,list: list);
return SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height / 1.4,
child: Column(
children: [
Expanded(
child: Consumer<ItemsVM>(
builder: (_, model, child) {
return Padding(
padding: const EdgeInsets.only(left: 20, right: 20, top: 6),
child: Column(
children: [
Row(
children: [
Expanded(
child: "Select Items"
.toText(fontSize: 24, isBold: true),
),
Center(
child: (model.serviceItems == null
? "0"
: model.serviceItems!.data!
.where((element) =>
element.isUpdateOrSelected == true)
.toList()
.length
.toString())
.toText(
fontSize: 10,
isBold: true,
color: Colors.white,
),
).toContainer(
borderRadius: 100,
width: 24,
height: 24,
paddingAll: 0,
backgroundColor: MyColors.darkPrimaryColor,
),
],
),
12.height,
TxtField(
hint: "Search Items",
onChanged: (v) {},
),
12.height,
Expanded(
child: model.serviceItems?.data == null
? const Center(child: CircularProgressIndicator())
: model.serviceItems?.data!.length == 0
? Center(child: "No Item Found".toText())
: ListView.separated(
itemBuilder:
(BuildContext context, int index) {
return Row(
children: [
Checkbox(
value: model
.serviceItems!
.data![index]
.isUpdateOrSelected,
onChanged: (bool? v) {
model.serviceItems!.data![index]
.isUpdateOrSelected = v;
model.notifyListeners();
},
),
12.width,
Expanded(
child: model.serviceItems!
.data![index].name!
.toText(),
),
],
);
},
separatorBuilder:
(BuildContext context, int index) {
return const Divider(
height: 1,
);
},
itemCount:
model.serviceItems?.data?.length ?? 0,
),
),
],
),
);
},
),
),
ShowFillButton(
title: 'Add Selected Items',
maxWidth: double.infinity,
margin: const EdgeInsets.all(20),
onPressed: () {
if (context.read<ItemsVM>().serviceItems != null) {
List<ItemData> list = [];
context.read<ItemsVM>().serviceItems!.data!.forEach((element) {
if (element.isUpdateOrSelected ?? false) {
list.add(element);
}
});
onSelectItems(list);
}
Navigator.pop(context);
},
)
],
),
);
}
}

@ -0,0 +1,185 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/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/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/txt_field.dart';
class ShowCollectPaymentSheet extends StatelessWidget {
Function() onClickYes;
Function() onClickNo;
ShowCollectPaymentSheet(
{required this.onClickYes, required this.onClickNo, Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 12),
child: Column(
children: [
"Do you want to collect the money before providing services?".toText(
fontSize: 24,
isBold: true,
),
21.height,
Row(
children: [
Expanded(
child: ShowFillButton(
title: "Yes",
onPressed: onClickYes,
),
),
12.width,
Expanded(
child: ShowFillButton(
title: "No",
isFilled: false,
txtColor: MyColors.darkPrimaryColor,
onPressed: onClickNo,
),
),
],
),
],
),
);
}
}
class Reason {
String title;
bool isSelected;
Reason(this.title, this.isSelected);
}
class CancelAppointmentReasonSheet extends StatefulWidget {
Function(String) onCancelClick;
CancelAppointmentReasonSheet({required this.onCancelClick, Key? key})
: super(key: key);
@override
State<CancelAppointmentReasonSheet> createState() =>
_CancelAppointmentReasonSheetState();
}
class _CancelAppointmentReasonSheetState
extends State<CancelAppointmentReasonSheet> {
String reason = "";
List<Reason> reasonList = [
Reason("Operational Issue", true),
Reason("Material Issue", false),
Reason("The customer no longer responding", false),
Reason("Other", false),
];
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(left: 21, right: 21, top: 12, bottom: 21),
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Reason".toText(fontSize: 24, isBold: true),
ListView.separated(
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.only(top: 12, bottom: 12),
child: Row(
children: [
Container(
width: 14,
height: 14,
decoration: BoxDecoration(
color: reasonList[index].isSelected
? MyColors.darkPrimaryColor
: Colors.transparent,
borderRadius: BorderRadius.circular(122),
border: Border.all(
color: reasonList[index].isSelected
? MyColors.darkPrimaryColor
: borderColor,
width: 1),
),
child: const Icon(
Icons.done,
size: 12,
color: Colors.white,
),
),
12.width,
reasonList[index].title.toText(isBold: true)
],
),
).onPress(() {
for (var element in reasonList) {
element.isSelected = false;
}
setState(() {
reason = reasonList[index].title;
reasonList[index].isSelected = true;
});
});
},
separatorBuilder: (context, index) {
return Container(
width: double.infinity,
height: 1,
color: MyColors.borderColor,
);
},
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: reasonList.length,
),
if (reason == "Other")
TxtField(
hint: "Type Here...",
maxLines: 5,
onChanged: (v) {
reason = v;
},
),
12.height,
Row(
children: [
Expanded(
child: ShowFillButton(
title: "No",
isFilled: false,
txtColor: MyColors.darkPrimaryColor,
onPressed: () {
pop(context);
},
),
),
12.width,
Expanded(
child: ShowFillButton(
title: "Yes",
onPressed: () {
if (reason.isEmpty || reason == "Other") {
Utils.showToast("Please Select Reason");
} else {
widget.onCancelClick(reason);
pop(context);
}
},
),
),
],
)
],
),
);
}
}

@ -1,19 +1,31 @@
import 'dart:async';
import 'package:badges/badges.dart' as b;
import 'package:car_provider_app/view_models/dashboard_view_model.dart';
import 'package:car_provider_app/view_models/service_view_model.dart';
import 'package:car_provider_app/views/dashboard/fragments/ads_fragment.dart';
import 'package:car_provider_app/views/dashboard/fragments/appoinment_fragment.dart';
import 'package:car_provider_app/views/dashboard/fragments/my_requests_fragment.dart';
import 'package:car_provider_app/views/dashboard/widget/drawer_widget.dart';
import 'package:car_provider_app/views/settings/branch/branch_list_page.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/view_models/chat_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/common_widgets/bottom_nav_bar.dart';
import 'package:provider/provider.dart';
import 'fragments/branch_appointment_fragment.dart';
import 'fragments/home_fragment.dart';
class DashboardPage extends StatefulWidget {
@ -39,17 +51,30 @@ class _DashboardPageState extends State<DashboardPage> {
Future<void> _onRefresh() async {
final requestsVM = context.read<RequestsVM>();
final adVM = context.read<AdVM>();
final serviceVM = context.read<ServiceVM>();
final chatVM = context.read<ChatVM>();
adVM.populateAdsFilterList();
serviceVM.getBranchAndServices();
if (adVM.myAds.isEmpty) {
await adVM.getMyAds();
// context.read<AdVM>().populateAdsFilterList();
context.read<ServiceVM>().getBranchAndServices();
AdVM adVm = Provider.of<AdVM>(context, listen: false);
AppointmentsVM appointmentsVM =
Provider.of<AppointmentsVM>(context, listen: false);
if (appointmentsVM.myAppointments.isEmpty) {
await appointmentsVM.getProviderMyAppointments({
"ServiceProviderID": injector
.get<AppState>()
.getUser
.data
?.userInfo
?.providerId
.toString() ??
"0"
});
}
if (adVm.myAds.isEmpty) {
await adVm.getMyAds();
}
if (adVM.exploreAds.isEmpty) {
await adVM.getExploreAds();
if (adVm.exploreAds.isEmpty) {
await adVm.getExploreAds();
}
if (requestsVM.myRequests.isEmpty) {
@ -57,6 +82,7 @@ class _DashboardPageState extends State<DashboardPage> {
}
await chatVM.buildHubConnection(context);
}
@override
@ -67,9 +93,9 @@ class _DashboardPageState extends State<DashboardPage> {
dashboardVM.updateIndex(2);
},
),
AppointmentFragment(
BranchAppointmentFragment(
onBackButtonTapped: () {
dashboardVM.updateIndex(2);
dashboardVM.updateIndex(2);
},
),
HomeFragment(
@ -79,6 +105,9 @@ class _DashboardPageState extends State<DashboardPage> {
onRefresh: () async {
_onRefresh();
},
onNotificaitonClick: () {
_onRefresh();
},
),
AdsFragment(
onBackButtonTapped: () {

@ -1,18 +1,52 @@
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:car_provider_app/views/dashboard/widget/appointment_slider_widget.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/date_helper.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/views/appointments/widgets/customer_appointment_slider_widget.dart';
import 'package:mc_common_app/widgets/common_widgets/categories_list.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/tab/menu_tabs.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/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'package:provider/provider.dart';
class AppointmentFragment extends StatelessWidget {
String date = "";
VoidCallback onBackButtonTapped;
AppointmentFragment({required this.onBackButtonTapped});
AppointmentFragment({Key? key, required this.onBackButtonTapped})
: super(key: key);
GlobalKey<RefreshIndicatorState> refreshIndicatorKey =
GlobalKey<RefreshIndicatorState>();
Future<void> _pullRefresh(BuildContext context) async {
await context.read<AppointmentsVM>().getProviderMyAppointments({
"ServiceProviderID": injector
.get<AppState>()
.getUser
.data
?.userInfo
?.providerId
.toString() ??
"0"
});
}
@override
Widget build(BuildContext context) {
context.read<AppointmentsVM>().setupProviderAppointmentFilter();
date = DateHelper.formatAsDayMonthYear(DateTime.now());
return Scaffold(
appBar: CustomAppBar(
profileImageUrl: MyAssets.carBanner,
@ -29,38 +63,180 @@ class AppointmentFragment extends StatelessWidget {
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: SingleChildScrollView(
child: Column(
children: [
12.height,
SizedBox(
height: 35,
width: double.infinity,
child: MenuTabs(
0,
[
DropValue(0, "All Appointments", ""),
DropValue(1, "Booked", ""),
DropValue(2, "Confirmed", ""),
DropValue(3, "Arrived", ""),
],
onSelect: (DropValue value) {},
child: Consumer(builder: (BuildContext context,
AppointmentsVM appointmentsVM, Widget? child) {
return RefreshIndicator(
onRefresh: () => _pullRefresh(context),
key: refreshIndicatorKey,
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
children: [
progressWidget(context),
FiltersList(
filterList: appointmentsVM.appointmentsFilterOptions,
padding: const EdgeInsets.symmetric(horizontal: 18),
onFilterTapped: (index, selectedFilterId) {
appointmentsVM.applyFilterOnAppointmentsVM(
appointmentStatusEnum:
selectedFilterId.toAppointmentStatusEnum(),
);
},
),
ListView.separated(
itemBuilder: (context, index) {
return AppointmentSliderWidget(
appointmentListModel:
appointmentsVM.myFilteredAppointments2[index],
isNeedTotalPayment: false,
onTap: () {
navigateWithName(
context,
ProviderAppRoutes.appointmentDetailList,
arguments: appointmentsVM
.myFilteredAppointments2[index]
.customerAppointmentList,
);
},
);
},
separatorBuilder: (context, snapchat) {
return 21.height;
},
itemCount: appointmentsVM.myFilteredAppointments2.length,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: const EdgeInsets.all(21),
),
],
),
),
);
}),
),
);
}
Widget progressWidget(BuildContext context) {
return Column(
children: [
Row(
children: [
Expanded(
child: "Slots Overview".toText(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Row(
children: [
date.toText(
fontWeight: FontWeight.bold,
),
const Icon(
Icons.keyboard_arrow_down_outlined,
size: 16,
),
],
)
.toContainer(
backgroundColor: MyColors.lightGreyEAColor,
borderRadius: 100,
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
),
ListView(
padding: const EdgeInsets.all(21),
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
)
.onPress(() async {
date = await Utils.pickDateFromDatePicker(
context,
firstDate: null,
);
context.read<AppointmentsVM>().notifyListeners();
}),
],
),
24.height,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
width: 14,
height: 14,
color: MyColors.lightGreyEAColor,
),
4.width,
"Empty: ".toText(
fontSize: 8,
color: Colors.white,
),
"8".toText(
fontSize: 9,
fontWeight: FontWeight.bold,
color: Colors.white,
),
],
).toContainer(
backgroundColor: MyColors.darkIconColor,
),
8.height,
Row(
children: [
Container(
width: 14,
height: 14,
color: MyColors.darkPrimaryColor,
),
4.width,
"Occupied: ".toText(
fontSize: 8,
color: Colors.white,
),
"54".toText(
fontSize: 9,
fontWeight: FontWeight.bold,
color: Colors.white,
),
],
).toContainer(
backgroundColor: MyColors.darkIconColor,
),
],
),
CircularPercentIndicator(
radius: 60.0,
lineWidth: 12.0,
percent: 0.7,
circularStrokeCap: CircularStrokeCap.round,
center: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const AppointmentSliderWidget(),
21.height,
const AppointmentSliderWidget(),
"Total Slots".toText(
fontSize: 13,
fontWeight: FontWeight.bold,
),
"24".toText(
fontSize: 24,
fontWeight: FontWeight.bold,
),
],
),
],
),
),
),
backgroundColor: MyColors.lightGreyEAColor,
progressColor: MyColors.darkPrimaryColor,
),
],
)
],
).toWhiteContainer(
width: double.infinity,
pading: const EdgeInsets.all(12),
margin: const EdgeInsets.all(21),
);
}
}

@ -0,0 +1,170 @@
import 'package:geolocator/geolocator.dart';
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:easy_localization/easy_localization.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/tab/role_type_tab.dart';
import '../../../generated/locale_keys.g.dart';
import '../../../view_models/service_view_model.dart';
import 'package:provider/provider.dart';
import 'package:flutter_svg/flutter_svg.dart';
class BranchAppointmentFragment extends StatelessWidget {
bool isNeedAppBar;
VoidCallback onBackButtonTapped;
BranchAppointmentFragment(
{Key? key, this.isNeedAppBar = true, required this.onBackButtonTapped})
: super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: !isNeedAppBar
? null
: CustomAppBar(
title: "Appointments",
onBackButtonTapped: onBackButtonTapped,
),
body: SizedBox(
width: double.infinity,
height: double.infinity,
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(left: 21, right: 21, top: 21),
child: RoleTypeTab(
context.watch<ServiceVM>().selectedBranchStatus == 3
? 0
: context.watch<ServiceVM>().selectedBranchStatus,
[
DropValue(3, "Active", ""),
DropValue(1, "Requested", ""),
],
onSelect: (DropValue value) {
context.read<ServiceVM>().updateSelectedBranchType(value.id);
},
),
),
Expanded(
child: Consumer<ServiceVM>(
builder: (context, model, _) {
if (model.state == ViewState.busy) {
return const Center(child: CircularProgressIndicator());
} else {
List<BranchDetailModel> branches = [];
if (model.branches!.data != null) {
branches = model.branches!.data!.serviceProviderBranch!
.where((element) =>
model.selectedBranchStatus == element.statusId)
.toList();
}
return branches.isEmpty
? Center(child: Text(LocaleKeys.no_branch.tr()))
: ListView.separated(
itemBuilder: (context, index) {
return Row(
children: [
Container(
width: 74,
height: 50,
decoration: const BoxDecoration(
color: MyColors.darkPrimaryColor,
borderRadius:
BorderRadius.all(Radius.circular(8)),
),
padding: const EdgeInsets.all(6),
child: SvgPicture.asset(
MyAssets.icBranches,
color: Colors.white,
),
),
12.width,
Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
mainAxisAlignment:
MainAxisAlignment.start,
children: [
Row(
children: [
const Icon(
Icons.place,
size: 12,
color: MyColors.darkPrimaryColor,
),
Geolocator.distanceBetween(
AppState()
.currentLocation
.latitude,
AppState()
.currentLocation
.latitude,
double.parse(branches[index]
.latitude ??
"0"),
double.parse(branches[index]
.longitude ??
"0"))
.toStringAsFixed(2)
.toText(
fontSize: 12,
color:
MyColors.darkPrimaryColor,
)
],
),
Text(
branches[index].branchName ?? "",
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
"Tap to view".toText(
fontSize: 10,
color: MyColors.grey70Color),
],
),
),
12.width,
],
).toContainer().onPress(() async {
branches[index].countryID =
model.branches!.data!.countryID;
branches[index].countryName =
model.branches!.data!.countryName;
navigateWithName(
context, ProviderAppRoutes.appointment,
arguments: branches[index]);
});
},
separatorBuilder: (context, index) {
return 12.height;
},
itemCount: branches.length,
padding: const EdgeInsets.all(12),
);
}
},
),
),
],
),
),
);
}
}

@ -1,16 +1,15 @@
import 'package:car_provider_app/views/dashboard/widget/my_service_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
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/view_models/chat_view_model.dart';
import 'package:mc_common_app/view_models/requests_view_model.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/views/advertisement/ads_list.dart';
import 'package:mc_common_app/views/appointments/widgets/customer_appointment_slider_widget.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/common_widgets/view_all_widget.dart';
@ -21,10 +20,15 @@ import 'package:provider/provider.dart';
import '../widget/appointment_slider_widget.dart';
class HomeFragment extends StatelessWidget {
VoidCallback onTap;
VoidCallback onTap, onNotificaitonClick;
RefreshCallback onRefresh;
HomeFragment({required this.onTap, required this.onRefresh, Key? key}) : super(key: key);
HomeFragment(
{required this.onTap,
required this.onRefresh,
required this.onNotificaitonClick,
Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
@ -35,19 +39,8 @@ class HomeFragment extends StatelessWidget {
profileImageUrl: MyAssets.carBanner,
onTap: onTap,
actions: [
Row(
children: [
"${AppState().currentAppType}".toText(color: MyColors.darkTextColor).onPress(() async {
print("myId: ${AppState().getUser.data!.userInfo!.userId}");
// final chatVM = context.read<ChatVM>();
// await chatVM.buildHubConnection();
}),
],
),
10.width,
IconButton(
onPressed: () {},
onPressed: onNotificaitonClick,
icon: const b.Badge(
badgeContent: Text(
'3',
@ -79,7 +72,17 @@ class HomeFragment extends StatelessWidget {
subTitle: 'View All',
onSubtitleTapped: () {},
).horPaddingMain(),
const AppointmentSliderWidget().horPaddingMain(),
// const AppointmentSliderWidget().horPaddingMain(),
CustomerAppointmentSliderWidget(
myUpComingAppointments:
context.read<AppointmentsVM>().myUpComingAppointments,
isNeedToShowEmptyMessage: true,
onAppointmentClick: (){
// navigateWithName(
// context, ProviderAppRoutes.appointment,
// arguments: branches[index]);
},
),
21.height,
ViewAllWidget(
title: 'My Branches',
@ -110,7 +113,8 @@ class HomeFragment extends StatelessWidget {
shouldShowAdStatus: true,
isAdsFragment: false,
adsList: adVM.myActiveAdsForHome,
scrollPhysics: const NeverScrollableScrollPhysics(),
scrollPhysics:
const NeverScrollableScrollPhysics(),
),
],
)
@ -130,9 +134,12 @@ class HomeFragment extends StatelessWidget {
).horPaddingMain(),
BuildAdsList(
shouldShowAdStatus: false,
adsList: adVM.exploreAds.length >= 3 ? adVM.exploreAds.take(3).toList() : adVM.exploreAds,
adsList: adVM.exploreAds.length >= 3
? adVM.exploreAds.take(3).toList()
: adVM.exploreAds,
isAdsFragment: false,
scrollPhysics: const NeverScrollableScrollPhysics(),
scrollPhysics:
const NeverScrollableScrollPhysics(),
),
],
)

@ -1,96 +1,353 @@
import 'package:car_provider_app/config/provider_routes.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/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:sizer/sizer.dart';
import 'package:flutter_svg/flutter_svg.dart';
class AppointmentSliderWidget extends StatelessWidget {
const AppointmentSliderWidget({Key? key}) : super(key: key);
AppointmentListModel appointmentListModel;
bool isNeedTotalPayment;
bool isNeedToShowItems;
bool isNeedToShowToMoreText;
bool isSelectable;
bool isNeedToShowAppointmentStatus;
bool isNeedToShowMergeStatus;
Function()? onTap;
AppointmentSliderWidget(
{required this.appointmentListModel,
required this.onTap,
this.isNeedTotalPayment = false,
this.isNeedToShowItems = false,
this.isNeedToShowToMoreText = true,
this.isSelectable = false,
this.isNeedToShowAppointmentStatus = false,
this.isNeedToShowMergeStatus = false,
Key? key})
: super(key: key);
List<Widget> buildServicesFromAppointment(
{required AppointmentListModel appointmentListModel}) {
if (appointmentListModel.appointmentServicesList == null ||
appointmentListModel.appointmentServicesList!.isEmpty) {
return [SizedBox()];
}
if (appointmentListModel.appointmentServicesList!.length == 1) {
List<Widget> itemsList = [];
if (isNeedToShowItems) {
itemsList = List.generate(
appointmentListModel
.appointmentServicesList?.first.serviceItems?.length ??
0,
(index) => (appointmentListModel.appointmentServicesList?.first
.serviceItems?[index].name ??
"")
.toString()
.toText(
color: MyColors.lightTextColor,
isBold: true,
),
);
}
return [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
showServices(
appointmentListModel
.appointmentServicesList![0].providerServiceDescription,
MyAssets.modificationsIcon,
),
if (isNeedToShowItems) ...itemsList,
],
)
];
}
List<Widget> servicesList = List.generate(
isNeedToShowToMoreText
? 2
: appointmentListModel.appointmentServicesList?.length ?? 0,
(index) {
List<Widget> itemsList = [];
if (isNeedToShowItems) {
itemsList = List.generate(
appointmentListModel
.appointmentServicesList?[index].serviceItems?.length ??
0,
(mIndex) =>
(" - ${appointmentListModel.appointmentServicesList?[index].serviceItems?[mIndex].name ?? ""}")
.toString()
.toText(
color: MyColors.lightTextColor,
isBold: true,
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
showServices(
appointmentListModel
.appointmentServicesList![index].providerServiceDescription,
MyAssets.modificationsIcon),
if (isNeedToShowItems) ...itemsList,
],
).paddingOnly(bottom: 4);
},
);
if (isNeedToShowToMoreText &&
appointmentListModel.appointmentServicesList!.length > 1) {
servicesList.add(
showServices(
"+ ${appointmentListModel.appointmentServicesList!.length - 1} More",
"",
isMoreText: true,
),
);
}
return servicesList;
}
@override
Widget build(BuildContext context) {
return Column(
return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
if (isSelectable)
SizedBox(
child: const SizedBox(
width: 14,
height: 14,
).toContainer(
borderRadius: 24,
marginAll: 4,
paddingAll: 0,
backgroundColor: (appointmentListModel.isSelected ?? false)
? MyColors.primaryColor
: MyColors.greyButtonColor,
),
).toContainer(
borderRadius: 24,
isEnabledBorder: true,
paddingAll: 0,
borderWidget: 3,
borderColor: MyColors.primaryColor,
),
if (isSelectable) 12.width,
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (isNeedToShowMergeStatus)
"Appointment Merged".toText(color: MyColors.white).toContainer(
padding: const EdgeInsets.symmetric(
horizontal: 6, vertical: 3),
borderRadius: 12,
backgroundColor: MyColors.greenColor,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Olaya Brach".toText(
fontSize: 12,
color: MyColors.darkTextColor,
isBold: true,
),
"Abdullah Alhbas".toText(
fontSize: 14,
isBold: true,
),
Row(
children: [
"Appt. On:".toText(
color: MyColors.lightTextColor,
),
2.width,
"19-Mar-2023 11:48 AM".toText(),
],
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
(appointmentListModel.branchName ?? "").toText(
fontSize: 12,
color: MyColors.darkTextColor,
isBold: true,
),
(appointmentListModel.customerName ?? "").toText(
color: MyColors.black, isBold: true, fontSize: 16),
Row(
children: [
"Phone:".toText(
color: MyColors.lightTextColor,
),
2.width,
appointmentListModel.customerMobileNum
.toString()
.toText(
fontSize: 12,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Appt. On:".toText(
color: MyColors.lightTextColor,
),
2.width,
Expanded(
child:
"${appointmentListModel.duration ?? ""} ${appointmentListModel.appointmentDate!.toFormattedDateWithoutTime()}"
.toText(
fontSize: 12,
),
),
],
),
Row(
children: [
"Location: ".toText(
color: MyColors.lightTextColor,
),
2.width,
appointmentListModel.appointmentType
.toString()
.toText(
fontSize: 12,
),
],
),
],
),
),
if (!isNeedTotalPayment)
if (appointmentListModel.customerAppointmentList!.length >
1)
"${appointmentListModel.customerAppointmentList!.length - 1}+ Appointments"
.toText(
fontSize: 8,
)
.toContainer(
borderRadius: 15,
backgroundColor: MyColors.lightGreyEAColor,
padding: const EdgeInsets.symmetric(
vertical: 6,
horizontal: 12,
),
),
if (isNeedToShowAppointmentStatus)
(appointmentListModel.appointmentStatusEnum!
.getAppointmentNameFromEnum())
.toText(color: MyColors.white)
.toContainer(
padding: const EdgeInsets.symmetric(
horizontal: 6, vertical: 3),
borderRadius: 12,
backgroundColor: MyColors.primaryColor,
),
],
),
),
"1+ Requests".toText(fontSize: 10).toContainer(
borderRadius: 15,
backgroundColor: MyColors.lightGreyEAColor,
padding: const EdgeInsets.symmetric(
vertical: 6,
horizontal: 12,
),
),
],
),
8.height,
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: Column(
8.height,
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
showServices("Maintenance"),
2.height,
showServices("Accessories and Modification"),
Expanded(
child: Column(
children: [
...buildServicesFromAppointment(
appointmentListModel: appointmentListModel),
if (isNeedTotalPayment)
Column(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
24.height,
"Total Amount".toText(
fontSize: 12,
color: MyColors.lightTextColor,
isBold: true,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
appointmentListModel.totalAmount
.toString()
.toText(fontSize: 16, isBold: true),
2.width,
"SAR:".toText(
color: MyColors.lightTextColor,
),
],
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
2.height,
"Remaining Amount".toText(
fontSize: 12,
color: MyColors.lightTextColor,
isBold: true,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
appointmentListModel.remainingAmount
.toString()
.toText(fontSize: 16, isBold: true),
2.width,
"SAR:".toText(
color: MyColors.lightTextColor,
),
],
),
],
),
],
)
],
),
),
if (!isNeedToShowItems)
const Icon(
Icons.arrow_forward,
),
],
),
),
const Icon(
Icons.arrow_forward,
),
],
),
],
),
)
],
).toWhiteContainer(
width: double.infinity,
allPading: 12,
onTap: () {
navigateWithName(context, ProviderAppRoutes.appointmentDetailList);
});
).toWhiteContainer(width: double.infinity, allPading: 12, onTap: onTap);
}
Widget showServices(String title) {
double calculateTotalPrice() {
double totalServiceListPrice = 0;
appointmentListModel.appointmentServicesList!.forEach((servicesElement) {
servicesElement.serviceItems!.forEach((itemsElement) {
totalServiceListPrice += double.parse(itemsElement.price ?? "0");
});
});
return totalServiceListPrice;
}
Widget showServices(String title, String icon, {bool isMoreText = false}) {
return Row(
children: [
const Icon(
Icons.ac_unit,
color: MyColors.primaryColor,
size: 18,
),
8.width,
title.toText(
fontSize: 14,
isBold: true,
if (icon != "") ...[
SvgPicture.asset(icon),
8.width,
],
Flexible(
child: title.toText(
fontSize: 12,
isBold: true,
color: isMoreText ? MyColors.primaryColor : MyColors.black,
),
),
],
);

@ -1,14 +1,19 @@
import 'dart:convert';
import 'dart:developer';
import 'package:car_provider_app/config/provider_routes.dart';
import 'package:car_provider_app/view_models/service_view_model.dart';
import 'package:car_provider_app/views/settings/services/services_list_page.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:car_provider_app/view_models/branch_view_model.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/categroy.dart';
import 'package:mc_common_app/theme/colors.dart';
@ -20,16 +25,18 @@ import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
import '../../../generated/locale_keys.g.dart';
class BranchDetailPage extends StatelessWidget {
final BranchDetailModel branchData;
BranchDetailModel branchData;
BranchDetailPage(this.branchData, {super.key});
BranchDetailPage(this.branchData);
List<CategoryData> categories = [];
@override
Widget build(BuildContext context) {
for (var element in branchData.branchServices!) {
branchData.branchServices!.forEach((element) {
categories.add(
CategoryData(
id: element.categoryId,
@ -37,15 +44,15 @@ class BranchDetailPage extends StatelessWidget {
categoryNameN: element.categoryName,
),
);
}
});
categories = categories.toSet().toList();
for (var payment in categories) {
for (var element in branchData.branchServices!) {
branchData.branchServices!.forEach((element) {
if (payment.id == element.categoryId) {
payment.services ??= [];
payment.services!.add(element);
}
}
});
}
branchData.categories = categories;
return Scaffold(

@ -1,11 +1,12 @@
// ignore_for_file: must_be_immutable
import 'package:car_provider_app/generated/locale_keys.g.dart';
import 'package:car_provider_app/view_models/service_view_model.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:car_provider_app/view_models/branch_view_model.dart';
import 'package:car_provider_app/views/location/pick_location_page.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/general_models/m_response.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/theme/colors.dart';
@ -22,7 +23,7 @@ import 'package:provider/provider.dart';
class DefineBranchPage extends StatelessWidget {
BranchDetailModel? branchData;
DefineBranchPage(this.branchData, {super.key});
DefineBranchPage(this.branchData);
@override
Widget build(BuildContext context) {

@ -282,6 +282,7 @@ class AddSchedulesPage extends StatelessWidget {
days.add(element.id);
}
//TODO: needs to verify with Zahoor about appointment type while creating Schedule
var map = {
"scheduleName": name,
"serviceProviderBranchID": scheduleData.branchId,
@ -292,6 +293,7 @@ class AddSchedulesPage extends StatelessWidget {
"slotDurationMinute": slotsTime,
"perSlotAppointment": appointmentPerSlot,
"deliveryServiceType": 1,
"appointmentType": 1,
"weeklyOffDays": days
};

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:car_provider_app/view_models/items_view_model.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/services_models/item_model.dart';
import 'package:mc_common_app/theme/colors.dart';

@ -112,7 +112,7 @@ class ItemsListPage extends StatelessWidget {
context,
ProviderAppRoutes.createItem,
arguments: ItemData(
serviceProviderServiceId: serviceProviderService!.serviceId,
serviceProviderServiceId: serviceProviderService!.serviceProviderServiceId,
),
);
},

Loading…
Cancel
Save