Services merging in Schedules (In Progress)

pull/3/head
FaizHashmiCS22 3 years ago
parent 436befd111
commit 533952e14e

@ -1,10 +1,12 @@
import 'package:car_customer_app/repositories/provider_repo.dart';
import 'package:car_customer_app/repositories/schedule_repo.dart';
import 'package:mc_common_app/config/dependencies.dart';
class CustomerDependencies {
static void addDependencies() {
AppDependencies.addDependencies();
injector.registerSingleton<ProviderRepo>(() => ProviderRepoImp());
injector.registerSingleton<ScheduleRepo>(() => ScheduleRepoImp());
}
}

@ -1,6 +1,8 @@
import 'package:car_customer_app/views/appointments/appointment_detail_view.dart';
import 'package:car_customer_app/views/appointments/book_appointment_services_view.dart';
import 'package:car_customer_app/views/appointments/book_appointments_item_view.dart';
import 'package:car_customer_app/views/appointments/pick_items_view.dart';
import 'package:car_customer_app/views/appointments/review_appointment_view.dart';
import 'package:car_customer_app/views/dashboard/dashboard_page.dart';
import 'package:car_customer_app/views/provider/branch_detail_page.dart';
import 'package:car_customer_app/views/provider/provider_profile_page.dart';
@ -21,6 +23,8 @@ class CustomerAppRoutes {
AppRoutes.adsDetailView: (context) => AdsDetailView(adDetails: ModalRoute.of(context)!.settings.arguments as AdDetailsModel),
AppRoutes.createAdView: (context) => CreateAdView(),
AppRoutes.bookAppointmenServicesView: (context) => BookAppointmentServicesView(),
AppRoutes.bookAppointmentsItemView: (context) => BookAppointmentsItemView(),
AppRoutes.reviewAppointmentView: (context) => ReviewAppointment(),
AppRoutes.paymentMethodsView: (context) => PaymentMethodsView(),
AppRoutes.branchDetailPage: (context) => BranchDetailPage(branchDetailModel: ModalRoute.of(context)!.settings.arguments as BranchDetailModel),
AppRoutes.providerProfilePage: (context) => ProviderProfilePage(providerId: ModalRoute.of(context)!.settings.arguments as int),

@ -1,6 +1,7 @@
import 'package:car_customer_app/config/customer_dependencies.dart';
import 'package:car_customer_app/config/customer_routes.dart';
import 'package:car_customer_app/repositories/provider_repo.dart';
import 'package:car_customer_app/repositories/schedule_repo.dart';
import 'package:car_customer_app/view_models/appointments_view_model.dart';
import 'package:car_customer_app/view_models/dashboard_view_model.dart';
import 'package:easy_localization/easy_localization.dart';
@ -26,7 +27,6 @@ import 'package:provider/provider.dart';
import 'package:provider/single_child_widget.dart';
import 'package:sizer/sizer.dart';
//test commit
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
@ -56,6 +56,7 @@ Future<void> main() async {
),
ChangeNotifierProvider<AppointmentsVM>(
create: (_) => AppointmentsVM(
scheduleRepo: injector.get<ScheduleRepo>(),
providerRepo: injector.get<ProviderRepo>(),
commonServices: injector.get<CommonAppServices>(),
commonRepo: injector.get<CommonRepo>(),

@ -12,7 +12,7 @@ import 'package:mc_common_app/models/services/item_model.dart';
abstract class ProviderRepo {
Future<List<BranchDetailModel>> getAllNearBranchAndServices();
Future<List<ServiceItemModel>> getServiceItems(int serviceId);
Future<List<ItemData>> getServiceItems(int serviceId);
Future<ProviderProfileModel> getBranchAndServices(int providerId);
}
@ -29,7 +29,7 @@ class ProviderRepoImp implements ProviderRepo {
}
@override
Future<List<ServiceItemModel>> getServiceItems(int serviceId) async {
Future<List<ItemData>> getServiceItems(int serviceId) async {
var queryParameters = {
"ServiceProviderServiceID": serviceId.toString(),
};
@ -40,7 +40,7 @@ class ProviderRepoImp implements ProviderRepo {
token: appState.getUser.data!.accessToken,
queryParameters: queryParameters,
);
List<ServiceItemModel> serviceItems = List.generate(adsGenericModel.data.length, (index) => ServiceItemModel.fromJson(adsGenericModel.data[index]));
List<ItemData> serviceItems = List.generate(adsGenericModel.data.length, (index) => ItemData.fromJson(adsGenericModel.data[index]));
return serviceItems;
}

@ -0,0 +1,70 @@
import 'package:mc_common_app/api/api_client.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/models/generic_resp_model.dart';
import 'package:mc_common_app/models/m_response.dart';
import 'package:mc_common_app/models/provider_branches_models/profile/services.dart';
import 'package:mc_common_app/models/schedule_model.dart';
abstract class ScheduleRepo {
Future<Services> getAllServices(String branchId);
Future<MResponse> createSchedule(Map map);
Future<MResponse> addServicesInSchedule(Map map);
Future<MResponse> updateSchedule(Map map);
Future<List<ScheduleData>> getSchedules(String branchId);
Future<MResponse> updateServicesInSchedule(Map map);
}
class ScheduleRepoImp implements ScheduleRepo {
@override
Future<Services> getAllServices(String branchId) async {
Map<String, dynamic> map = {"ProviderBranchID": branchId};
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().getJsonForObject((json) => Services.fromJson(json), ApiConsts.getServicesOfBranch, token: t, queryParameters: map);
}
@override
Future<MResponse> createSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createSchedule, map, token: t);
}
@override
Future<MResponse> addServicesInSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.createGroup, map, token: t);
}
@override
Future<List<ScheduleData>> getSchedules(String branchId) async {
Map<String, dynamic> map = {"ServiceProviderBranchID": branchId};
String t = AppState().getUser.data!.accessToken ?? "";
GenericRespModel adsGenericModel = await injector.get<ApiClient>().getJsonForObject(
(json) => GenericRespModel.fromJson(json),
ApiConsts.getSchedule,
token: t,
queryParameters: map,
);
return List.generate(adsGenericModel.data.length, (index) => ScheduleData.fromJson(adsGenericModel.data[index]));
}
@override
Future<MResponse> updateSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateSchedule, map, token: t);
}
@override
Future<MResponse> updateServicesInSchedule(Map map) async {
String t = AppState().getUser.data!.accessToken ?? "";
return await injector.get<ApiClient>().postJsonForObject((json) => MResponse.fromJson(json), ApiConsts.updateGroup, map, token: t);
}
}

@ -1,8 +1,12 @@
import 'dart:developer';
import 'package:car_customer_app/repositories/provider_repo.dart';
import 'package:car_customer_app/repositories/schedule_repo.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart';
import 'package:mc_common_app/models/provider_branches_models/branch_detail_model.dart';
import 'package:mc_common_app/models/provider_branches_models/provider_profile_model.dart';
import 'package:mc_common_app/models/schedule_model.dart';
import 'package:mc_common_app/models/services/item_model.dart';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/widgets_models.dart';
@ -16,20 +20,29 @@ class AppointmentsVM extends BaseVM {
final CommonRepo commonRepo;
final CommonAppServices commonServices;
final ProviderRepo providerRepo;
final ScheduleRepo scheduleRepo;
AppointmentsVM({required this.commonServices, required this.providerRepo, required this.commonRepo});
AppointmentsVM({required this.commonServices, required this.scheduleRepo, required this.providerRepo, required this.commonRepo});
bool isFetchingLists = false;
List<AppointmentListModel> myAppointments = [];
List<FilterListModel> appointmentsFilterOptions = [];
List<ScheduleData> availableSchedules = [];
bool isFetchingServices = false;
List<DropValue> branchCategories = [];
bool isHomeTapped = false;
Future<void> getSchedulesByBranchId() async {
availableSchedules = await scheduleRepo.getSchedules(selectedBranchModel!.id!.toString());
log("schedules: ${availableSchedules.toString()}");
notifyListeners();
}
void updateIsHomeTapped(bool value) {
isHomeTapped = value;
notifyListeners();
@ -39,38 +52,38 @@ class AppointmentsVM extends BaseVM {
void updatePickedHomeLocation(String value) {
pickedHomeLocation = value;
pickHomeLocationError = "";
notifyListeners();
}
SelectionModel branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
void updateProviderCategoryId(SelectionModel id) async {
void updateProviderCategoryId(SelectionModel id) {
branchSelectedCategoryId = id;
await getProviderServices(id.selectedId);
getBranchServices(categoryId: branchSelectedCategoryId.selectedId);
notifyListeners();
}
List<ServiceModel> branchServices = [];
List<FilterListModel> providersFilterOptions = [];
List<BranchDetailModel> nearbyBranches = [];
BranchDetailModel? selectedBranchModel;
SelectionModel branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
List<ServiceModel> branchServices = [];
ServiceModel? currentServiceSelection;
void updateBranchServiceId(SelectionModel id) async {
branchSelectedServiceId = id;
currentServiceSelection = branchServices.firstWhere((element) => element.serviceProviderServiceId == id.selectedId);
notifyListeners();
}
getProviderServices(int categoryId) async {
branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
resetCategorySelectionBottomSheet() {
selectedSubServicesCounter = 0;
branchSelectedCategoryId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
isHomeTapped = false;
pickedHomeLocation = "";
if (categoryId != -1) {
isFetchingServices = true;
notifyListeners();
// branchServices = await commonRepo.getProviderServices(categoryId: categoryId);
isFetchingServices = false;
notifyListeners();
}
branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
currentServiceSelection = null;
}
populateAppointmentsFilterList() {
@ -101,11 +114,39 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
List<FilterListModel> providersFilterOptions = [];
List<BranchDetailModel> nearbyBranches = [];
List<ServiceItemModel> serviceItems = [];
updateSelectedBranch(BranchDetailModel branchDetailModel) {
selectedBranchModel = branchDetailModel;
getBranchCategories();
notifyListeners();
}
List<ItemData> serviceItems = [];
List<ItemData> selectedServiceItems = [];
ProviderProfileModel? providerProfileModel;
int selectedSubServicesCounter = 0;
updateSelectedSubServicesCounter(int value) {
selectedSubServicesCounter = value;
notifyListeners();
}
onItemUpdateOrSelected(int index, bool selected, int itemId) {
serviceItems[index].isUpdateOrSelected = selected;
if (selected) {
selectedSubServicesCounter = selectedSubServicesCounter + 1;
updateSelectedSubServicesCounter(selectedSubServicesCounter);
selectSubServicesError = "";
currentServiceSelection!.serviceItems!.add(serviceItems[index]);
}
if (!selected) {
selectedSubServicesCounter = selectedSubServicesCounter - 1;
updateSelectedSubServicesCounter(selectedSubServicesCounter);
currentServiceSelection!.serviceItems!.removeWhere((element) => element.id == itemId);
}
notifyListeners();
}
populateProvidersFilterList() {
providersFilterOptions.clear();
providersFilterOptions = [
@ -128,7 +169,6 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
//Create new branch
getAllNearBranches({bool isNeedToRebuild = false}) async {
//TODO: needs to lat,long into API
nearbyBranches.clear();
@ -137,7 +177,7 @@ class AppointmentsVM extends BaseVM {
setState(ViewState.idle);
}
Future<List<ServiceItemModel>> getServiceItems(int serviceId) async {
Future<List<ItemData>> getServiceItems(int serviceId) async {
serviceItems.clear();
serviceItems = await providerRepo.getServiceItems(serviceId);
setState(ViewState.idle);
@ -151,8 +191,9 @@ class AppointmentsVM extends BaseVM {
}
String pickHomeLocationError = "";
String selectSubServicesError = "";
SelectionModel branchServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
SelectionModel branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
bool isCategoryAlreadyPresent(int id) {
final contain = branchCategories.where((element) => element.id == id);
@ -163,7 +204,7 @@ class AppointmentsVM extends BaseVM {
}
void getBranchCategories() async {
for (var value in branchServices) {
for (var value in selectedBranchModel!.branchServices!) {
if (!isCategoryAlreadyPresent(value.categoryId!)) {
branchCategories.add(DropValue(value.categoryId!, value.categoryName!, ""));
}
@ -171,24 +212,24 @@ class AppointmentsVM extends BaseVM {
notifyListeners();
}
getBranchServices(int categoryId) async {
branchServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
getBranchServices({required int categoryId}) async {
branchSelectedServiceId = SelectionModel(selectedOption: "", selectedId: -1, errorValue: "");
isHomeTapped = false;
pickedHomeLocation = "";
pickHomeLocationError = "";
if (categoryId != -1) {
isFetchingServices = true;
notifyListeners();
branchServices = getFilteredBranchServices(categoryId: categoryId, branchId: 6);
// notifyListeners();
branchServices = getFilteredBranchServices(categoryId: categoryId);
isFetchingServices = false;
notifyListeners();
}
}
List<ServiceModel> getFilteredBranchServices({required int branchId, required int categoryId}) {
// List<BranchServices> filteredServices = nearbyBranchesList.where((element) => element)
return [];
List<ServiceModel> getFilteredBranchServices({required int categoryId}) {
List<ServiceModel> filteredServices = selectedBranchModel!.branchServices!.where((element) => element.categoryId == categoryId).toList();
log("returning: ${filteredServices.toString()}");
return filteredServices;
}
void updatePickHomeLocationError(String value) {
@ -197,7 +238,7 @@ class AppointmentsVM extends BaseVM {
}
bool isServiceSelectionValidated() {
if (branchServiceId.selectedId == -1) {
if (branchSelectedServiceId.selectedId == -1) {
return false;
}
@ -209,4 +250,24 @@ class AppointmentsVM extends BaseVM {
}
return true;
}
bool onSubServicesNextPressed() {
for (var value in serviceItems) {
if (value.isUpdateOrSelected!) {
return true;
}
}
selectSubServicesError = "Please select at least one sub service";
notifyListeners();
return false;
}
void mergeServiceInAvailableSchedule() {
for (var schedule in availableSchedules) {
for (var service in schedule.scheduleServices!) {
if (branchSelectedServiceId.selectedId == service.serviceId) {}
schedule.selectedServices!.add(currentServiceSelection!);
}
}
}
}

@ -5,6 +5,9 @@ import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/schedule_model.dart';
import 'package:mc_common_app/models/services/item_model.dart';
import 'package:mc_common_app/models/services/service_model.dart';
import 'package:mc_common_app/models/widgets_models.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
@ -148,15 +151,16 @@ class BookAppointmentServicesView extends StatelessWidget {
10.height,
ListView.builder(
shrinkWrap: true,
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
itemCount: appointmentsVM.availableSchedules.where((element) => element.selectedServices!.isNotEmpty).toList().length,
itemBuilder: (BuildContext context, int scheduleIndex) {
ScheduleData scheduleData = appointmentsVM.availableSchedules.where((element) => element.selectedServices!.isNotEmpty).toList()[scheduleIndex];
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: "Mechanic".toText(fontSize: 16, isBold: true),
child: "Schedule: ${scheduleData.scheduleName}".toText(fontSize: 20, isBold: true),
),
Align(
alignment: Alignment.topRight,
@ -164,60 +168,84 @@ class BookAppointmentServicesView extends StatelessWidget {
).onPress(() {}),
],
),
Builder(builder: (context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
if (true) ...[
5.height,
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (true) ...[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
("Available Slots").toText(fontSize: 14, isBold: true),
],
),
5.height,
SizedBox(
width: double.infinity,
child: BuildTimeSlots(
timeSlots: _dummySlots,
onPressed: (index) => null,
),
),
],
20.height,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListView.separated(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: scheduleData.selectedServices!.length,
itemBuilder: (BuildContext context, int serviceIndex) {
ServiceModel selectedService = scheduleData.selectedServices![serviceIndex];
return Column(
children: [
"Service Location: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
("Home").toText(fontSize: 12, isBold: true).expand(),
],
),
8.height,
Column(
children: List.generate(
5,
(index) => Row(
crossAxisAlignment: CrossAxisAlignment.start,
Row(
children: [
"Gear Kit: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
("200 SAR").toText(fontSize: 12, isBold: true).expand(),
Expanded(
child: "${selectedService.serviceDescription}".toText(fontSize: 15, isBold: true),
),
],
),
),
),
8.height,
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"120".toText(fontSize: 29, isBold: true),
2.width,
"SAR".toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
Icon(
Icons.arrow_drop_down,
size: 30,
)
if (true) ...[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Service Location: ".toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true),
("Home").toText(fontSize: 12, isBold: true).expand(),
],
),
8.height,
Column(
children: List.generate(scheduleData.selectedServices![serviceIndex].serviceItems!.length, (itemIndex) {
ItemData itemData = selectedService.serviceItems![itemIndex];
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"${itemData.name}: ".toText(fontSize: 13, color: MyColors.lightTextColor, isBold: true),
("${itemData.price}").toText(fontSize: 13, isBold: true).expand(),
],
);
}),
),
8.height,
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"120".toText(fontSize: 29, isBold: true),
2.width,
"SAR".toText(color: MyColors.lightTextColor, fontSize: 16, isBold: true).paddingOnly(bottom: 5),
Icon(
Icons.arrow_drop_down,
size: 30,
)
],
).onPress(() => priceBreakDownClicked(context)),
],
],
).onPress(() => priceBreakDownClicked(context)),
],
if (true) ...[
8.height,
("Available Slots").toText(fontSize: 14, isBold: true),
5.height,
SizedBox(
width: double.infinity,
child: BuildTimeSlots(
timeSlots: _dummySlots,
onPressed: (index) => null,
),
),
],
],
);
}),
);
},
separatorBuilder: (BuildContext context, int index) => Divider(thickness: 2),
)
],
),
],
).toWhiteContainer(width: double.infinity, allPading: 12, margin: const EdgeInsets.symmetric(horizontal: 21, vertical: 10));
},

@ -4,7 +4,10 @@ import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/services/item_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
@ -33,7 +36,7 @@ class BookAppointmentsItemView extends StatelessWidget {
width: double.infinity,
color: MyColors.darkTextColor,
alignment: Alignment.centerLeft,
child: "3 Items Selected".toText(fontSize: 16, color: MyColors.white).horPaddingMain(),
child: "${appointmentsVM.selectedSubServicesCounter} Item(s) Selected".toText(fontSize: 16, color: MyColors.white).horPaddingMain(),
),
16.height,
Column(
@ -53,33 +56,46 @@ class BookAppointmentsItemView extends StatelessWidget {
Divider(),
],
).horPaddingMain(),
ListView.separated(
separatorBuilder: (BuildContext context, int index) => Divider(),
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
return ServiceItemWithPriceCheckBox(
description: "Some description about the sub-services",
title: "Engine Check",
isSelected: true,
onSelection: (bool value) {},
priceWidget: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
// TODO: This Price will be decided according to the service selected
150.toString().toText(fontSize: 30, isBold: true),
"SAR".toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5),
],
),
);
},
).expand(),
appointmentsVM.serviceItems.isEmpty
? Expanded(child: Center(child: "No Items to show.".toText(fontSize: 16, color: MyColors.lightTextColor)))
: ListView.separated(
separatorBuilder: (BuildContext context, int index) => Divider(),
itemCount: appointmentsVM.serviceItems.length,
itemBuilder: (BuildContext context, int index) {
ItemData itemData = appointmentsVM.serviceItems[index];
return ServiceItemWithPriceCheckBox(
description: "Some description about the sub-services",
title: itemData.name!,
isSelected: itemData.isUpdateOrSelected!,
onSelection: (bool value) {
appointmentsVM.onItemUpdateOrSelected(index, !itemData.isUpdateOrSelected!, itemData!.id!);
},
priceWidget: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
// TODO: This Price will be decided according to the service selected
itemData.price!.split(".").first.toText(fontSize: 30, isBold: true),
" SAR".toText(fontSize: 15, isBold: true, color: MyColors.lightTextColor).paddingOnly(bottom: 5),
],
),
);
},
).expand(),
Column(
children: [
Divider(
height: 1,
thickness: 0.7,
),
16.height,
8.height,
if (appointmentsVM.selectSubServicesError != "")
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
appointmentsVM.selectSubServicesError.toText(fontSize: 14, color: Colors.red),
],
).paddingOnly(right: 10),
8.height,
Row(
children: [
Expanded(
@ -87,7 +103,10 @@ class BookAppointmentsItemView extends StatelessWidget {
txtColor: MyColors.black,
maxHeight: 55,
title: "Cancel",
onPressed: () {},
onPressed: () {
appointmentsVM.resetCategorySelectionBottomSheet();
pop(context);
},
backgroundColor: MyColors.greyButtonColor,
),
),
@ -96,8 +115,22 @@ class BookAppointmentsItemView extends StatelessWidget {
child: ShowFillButton(
maxHeight: 55,
title: "Next",
onPressed: () {},
backgroundColor: MyColors.darkPrimaryColor,
onPressed: () async {
bool resp = appointmentsVM.onSubServicesNextPressed();
if (resp) {
Utils.showLoading(context);
if (appointmentsVM.availableSchedules.isEmpty) {
await appointmentsVM.getSchedulesByBranchId();
}
appointmentsVM.mergeServiceInAvailableSchedule();
Utils.hideLoading(context);
pop(context);
pop(context);
appointmentsVM.resetCategorySelectionBottomSheet();
}
},
backgroundColor: !appointmentsVM.isServiceSelectionValidated() ? MyColors.lightTextColor.withOpacity(0.6) : MyColors.primaryColor,
),
),
],

@ -62,19 +62,27 @@ class AppointmentServicePickBottomSheet extends StatelessWidget {
builder: (context) {
List<DropValue> serviceCategories = [];
for (var element in appointmentsVM.branchServices) {
serviceCategories.add(DropValue(element.serviceProviderServiceId ?? 0, element.serviceProviderServiceId.toString(), ""));
if (element.categoryId == appointmentsVM.branchSelectedCategoryId.selectedId) {
serviceCategories.add(DropValue(
element.serviceProviderServiceId ?? 0,
element.serviceDescription!,
"",
));
}
}
return DropdownField(
(DropValue value) => appointmentsVM.updateBranchServiceId(SelectionModel(selectedId: value.id, selectedOption: value.value, itemPrice: value.subValue)),
list: serviceCategories,
hint: "Select Services",
dropdownValue:
appointmentsVM.branchServiceId.selectedId != -1 ? DropValue(appointmentsVM.branchServiceId.selectedId, appointmentsVM.branchServiceId.selectedOption, "") : null,
hint: "Select Service",
dropdownValue: appointmentsVM.branchSelectedServiceId.selectedId != -1
? DropValue(appointmentsVM.branchSelectedServiceId.selectedId, appointmentsVM.branchSelectedServiceId.selectedOption, "")
: null,
);
},
),
],
if (appointmentsVM.branchServiceId.selectedId != -1 && !appointmentsVM.isFetchingServices) ...[
if (appointmentsVM.branchSelectedServiceId.selectedId != -1 && !appointmentsVM.isFetchingServices) ...[
16.height,
Row(
children: [
@ -171,6 +179,7 @@ class AppointmentServicePickBottomSheet extends StatelessWidget {
onPressed: () {
bool isValidated = appointmentsVM.isServiceSelectionValidated();
if (isValidated) {
appointmentsVM.getServiceItems(appointmentsVM.branchSelectedServiceId.selectedId);
navigateWithName(context, AppRoutes.bookAppointmentsItemView);
}
},

@ -53,6 +53,7 @@ class BranchesFragment extends StatelessWidget {
itemCount: model.nearbyBranches.length,
itemBuilder: (context, index) {
BranchDetailModel branchDetailModel = model.nearbyBranches[index];
return ProviderDetailsCard(
onCardTapped: () {
navigateWithName(context, AppRoutes.branchDetailPage, arguments: branchDetailModel);
@ -62,7 +63,7 @@ class BranchesFragment extends StatelessWidget {
providerLocation: branchDetailModel.distanceKm.toString() + " KM",
providerName: branchDetailModel.serviceProviderName ?? "",
providerRatings: "4.9",
items: branchDetailModel.branchServices,
services: branchDetailModel.branchServices,
);
},
separatorBuilder: (context, index) {

@ -1,3 +1,4 @@
import 'package:car_customer_app/view_models/appointments_view_model.dart';
import 'package:car_customer_app/views/provider/sheet/items_list_sheet.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
@ -13,6 +14,7 @@ import 'package:mc_common_app/widgets/bottom_sheet.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
class BranchDetailPage extends StatefulWidget {
final BranchDetailModel branchDetailModel;
@ -28,7 +30,7 @@ class _BranchDetailPageState extends State<BranchDetailPage> {
void initState() {
// TODO: implement initState
super.initState();
if (widget.branchDetailModel.branchServices!.length > 0) widget.branchDetailModel.branchServices?.first.isExpanded = true;
if (widget.branchDetailModel.branchServices!.length > 0) widget.branchDetailModel.branchServices?.first.isExpandedOrSelected = true;
}
@override
@ -151,6 +153,7 @@ class _BranchDetailPageState extends State<BranchDetailPage> {
margin: EdgeInsets.all(21),
onPressed: () {
navigateWithName(context, AppRoutes.bookAppointmenServicesView);
context.read<AppointmentsVM>().updateSelectedBranch(widget.branchDetailModel);
},
).toContainer(
paddingAll: 0,
@ -192,13 +195,13 @@ class _BranchDetailPageState extends State<BranchDetailPage> {
],
onExpansionChanged: (value) {
setState(() {
widget.branchDetailModel.branchServices![index].isExpanded = value;
widget.branchDetailModel.branchServices![index].isExpandedOrSelected = value;
});
},
backgroundColor: Colors.transparent,
collapsedBackgroundColor: Colors.transparent,
initiallyExpanded: widget.branchDetailModel.branchServices![index].isExpanded,
trailing: widget.branchDetailModel.branchServices![index].isExpanded ? Icon(Icons.keyboard_arrow_up) : Icon(Icons.keyboard_arrow_down),
initiallyExpanded: widget.branchDetailModel.branchServices![index].isExpandedOrSelected,
trailing: widget.branchDetailModel.branchServices![index].isExpandedOrSelected ? Icon(Icons.keyboard_arrow_up) : Icon(Icons.keyboard_arrow_down),
);
},
separatorBuilder: (context, index) {

@ -92,7 +92,7 @@ class _ProviderProfilePageState extends State<ProviderProfilePage> {
providerLocation: model.providerProfileModel!.serviceProviderBranch![index].distanceKm.toString() + " KM",
providerName: model.providerProfileModel!.serviceProviderBranch![index].serviceProviderName ?? "",
providerRatings: "4.9",
items: model.providerProfileModel!.serviceProviderBranch![index].branchServices,
services: model.providerProfileModel!.serviceProviderBranch![index].branchServices,
);
},
separatorBuilder: (context, index) {

@ -35,7 +35,7 @@ class _ItemsListSheetState extends State<ItemsListSheet> {
: ListView.separated(
itemCount: appointmentsVM.serviceItems.length,
itemBuilder: (BuildContext context, int index) {
ServiceItemModel serviceItemModel = appointmentsVM.serviceItems[index];
ItemData serviceItemModel = appointmentsVM.serviceItems[index];
return SizedBox(
width: double.infinity,
child: Row(
@ -47,7 +47,7 @@ class _ItemsListSheetState extends State<ItemsListSheet> {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
serviceItemModel.name.toString().toText(fontSize: 16, isBold: true),
serviceItemModel.toString().toText(fontSize: 16, isBold: true),
4.height,
showItem("Available for appointment:", (serviceItemModel.isAllowAppointment ?? false) ? "Yes" : "No", valueColor: Colors.green),
showItem("Allowing Workshop service:", (serviceItemModel.isAppointmentCompanyLoc ?? false) ? "Yes" : "No", valueColor: Colors.green),

Loading…
Cancel
Save