diff --git a/lib/config/customer_routes.dart b/lib/config/customer_routes.dart index 3345264..ad6774b 100644 --- a/lib/config/customer_routes.dart +++ b/lib/config/customer_routes.dart @@ -2,10 +2,12 @@ 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/pick_items_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:flutter/cupertino.dart'; import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/models/advertisment_models/ad_details_model.dart'; import 'package:mc_common_app/models/appointments_models/appointment_list_model.dart'; +import 'package:mc_common_app/models/services/branch_model.dart'; import 'package:mc_common_app/views/advertisement/ads_detail_view.dart'; import 'package:mc_common_app/views/advertisement/create_ad_view.dart'; import 'package:mc_common_app/views/payments/payment_methods_view.dart'; @@ -19,5 +21,6 @@ class CustomerAppRoutes { AppRoutes.createAdView: (context) => CreateAdView(), AppRoutes.bookAppointmenServicesView: (context) => BookAppointmentServicesView(), AppRoutes.paymentMethodsView: (context) => PaymentMethodsView(), + AppRoutes.branchDetailPage: (context) => BranchDetailPage(branchModel: ModalRoute.of(context)!.settings.arguments as BranchModel), }; } diff --git a/lib/repositories/provider_repo.dart b/lib/repositories/provider_repo.dart index a0d63e6..4f0c64f 100644 --- a/lib/repositories/provider_repo.dart +++ b/lib/repositories/provider_repo.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; +import 'package:mc_common_app/models/services/near_branch_model.dart'; import 'package:http/http.dart' as http; import 'package:mc_common_app/api/api_client.dart'; @@ -17,14 +18,14 @@ import 'package:mc_common_app/models/profile/services.dart'; import 'package:flutter/cupertino.dart'; abstract class ProviderRepo { - Future getBranchAndServices(); + Future getAllNearBranchAndServices(); } class ProviderRepoImp implements ProviderRepo { @override - Future getBranchAndServices() async { + Future getAllNearBranchAndServices() async { // var postParams = {"serviceProviderID": AppState().getUser.data?.userInfo?.providerId.toString() ?? ""}; String t = AppState().getUser.data!.accessToken ?? ""; - return await injector.get().getJsonForObject((json) => Branch2.fromJson(json), ApiConsts.BranchesAndServices, token: t); + return await injector.get().getJsonForObject((json) => NearBrancheModel.fromJson(json), ApiConsts.GetAllNearBranches, token: t); } } diff --git a/lib/view_models/providers_view_model.dart b/lib/view_models/providers_view_model.dart index 96ad83e..873c3f9 100644 --- a/lib/view_models/providers_view_model.dart +++ b/lib/view_models/providers_view_model.dart @@ -1,3 +1,4 @@ +import 'package:mc_common_app/models/services/near_branch_model.dart'; import 'package:car_customer_app/repositories/provider_repo.dart'; import 'package:flutter/cupertino.dart'; import 'package:mc_common_app/models/model/branch2.dart'; @@ -15,7 +16,7 @@ class ProvidersVM extends BaseVM { ProvidersVM({required this.commonServices, required this.commonRepo, required this.providerRepo}); List providersFilterOptions = []; - Branch2? branches; + NearBrancheModel? branches; populateProvidersFilterList() { providersFilterOptions.clear(); @@ -40,10 +41,11 @@ class ProvidersVM extends BaseVM { } //Create new branch - getAllNearBranches() async { + getAllNearBranches({bool isNeedToRebuild = false}) async { //TODO: needs to lat,long into API branches = null; - branches = await providerRepo.getBranchAndServices(); + if (isNeedToRebuild) setState(ViewState.busy); + branches = await providerRepo.getAllNearBranchAndServices(); setState(ViewState.idle); } } diff --git a/lib/views/appointments/pick_items_view.dart b/lib/views/appointments/pick_items_view.dart index 0a51fa6..bd8c1e6 100644 --- a/lib/views/appointments/pick_items_view.dart +++ b/lib/views/appointments/pick_items_view.dart @@ -42,7 +42,7 @@ class _BookProviderAppViewState extends State { onCardTapped: () {}, providerImageUrl: MyAssets.bnCar, providerLocation: "3km", - providerName: "Al Ahmed Maintenance", + title: "Al Ahmed Maintenance", providerRatings: "4.9", ), 12.height, @@ -90,19 +90,19 @@ class ServicesSelectionSection extends StatelessWidget { "Select services you want".toText(fontSize: 18, isBold: true), 8.height, DropdownField( - (DropValue value) {}, + (DropValue value) {}, list: dropList, hint: "Select service type", ), 8.height, DropdownField( - (DropValue value) {}, + (DropValue value) {}, list: dropList, hint: "Select service type", ), 8.height, DropdownField( - (DropValue value) {}, + (DropValue value) {}, list: dropList, hint: "Select service type", ), @@ -110,7 +110,7 @@ class ServicesSelectionSection extends StatelessWidget { "Select date and time".toText(fontSize: 18, isBold: true), 8.height, DropdownField( - (DropValue value) {}, + (DropValue value) {}, list: dropList, hint: "Select service type", ), diff --git a/lib/views/dashboard/fragments/branches_fragment.dart b/lib/views/dashboard/fragments/branches_fragment.dart index 5915432..d0ab34c 100644 --- a/lib/views/dashboard/fragments/branches_fragment.dart +++ b/lib/views/dashboard/fragments/branches_fragment.dart @@ -2,20 +2,16 @@ import 'package:car_customer_app/view_models/providers_view_model.dart'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/consts.dart'; - +import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; -import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; - +import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/widgets/common_widgets/categories_list.dart'; - -import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; +import 'package:mc_common_app/widgets/common_widgets/provider_details_card.dart'; import 'package:provider/provider.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import 'package:geolocator/geolocator.dart'; class BranchesFragment extends StatelessWidget { const BranchesFragment({Key? key}) : super(key: key); @@ -36,124 +32,47 @@ class BranchesFragment extends StatelessWidget { onFilterTapped: (index, selectedFilterId) => providersVM.applyFilterOnProviders(index: index), ), 16.height, - // Expanded( - // child: Container( - // child: ListView.builder( - // shrinkWrap: true, - // itemCount: 30, - // itemBuilder: (BuildContext context, int index) { - // return ProviderDetailsCard( - // onCardTapped: () { - // if (context.read().providerCategories.isEmpty) { - // context.read().getProviderCategories(); - // } - // navigateWithName(context, AppRoutes.bookAppointmenServicesView); - // }, - // providerImageUrl: MyAssets.bnCar, - // providerLocation: " 3km", - // providerName: "Al Ahmed Maintenance", - // providerRatings: "4.9", - // ); - // }, - // ), - // ), - // ), - Expanded( child: RefreshIndicator( onRefresh: () async { - context.read().getAllNearBranches(); + context.read().getAllNearBranches(isNeedToRebuild: true); }, - child: SizedBox( - width: double.infinity, - height: double.infinity, - child: Consumer( - builder: (context, model, _) { - if (model.state == ViewState.busy) { - return const Center(child: CircularProgressIndicator()); - } else { - return model.branches?.data == null - ? const Center(child: Text("No Branch Found")) - : model.branches!.data!.serviceProviderBranch!.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, - ), - //TODO: needs to implement get user location after login - Geolocator.distanceBetween( - // AppState().currentLocation.latitude, - // AppState().currentLocation.latitude, - 24.700590, - 46.670110, - double.parse(model.branches!.data!.serviceProviderBranch![index].latitude ?? "0"), - double.parse(model.branches!.data!.serviceProviderBranch![index].longitude ?? "0")) - .toStringAsFixed(2) - .toText( - fontSize: 12, - color: MyColors.darkPrimaryColor, - ) - ], - ), - Text( - model.branches!.data!.serviceProviderBranch![index].branchName ?? "", - style: const TextStyle( - fontSize: 14, - fontWeight: FontWeight.bold, - ), - ), - LocaleKeys.tapToEdit.tr().toText(fontSize: 10, color: MyColors.grey70Color), - ], - ), - ), - 12.width, - const Icon( - Icons.arrow_forward_rounded, - size: 16, - ), - ], - ).toContainer().onPress(() async { - // await navigateWithName(context, AppRoutes.defineBranch, arguments: snapshot.data!.data![index]); - // setState(() {}); - // model.branchs!.data!.serviceProviderBranch![index].countryID = model.branchs!.data!.countryID; - // model.branchs!.data!.serviceProviderBranch![index].countryName = model.branchs!.data!.countryName; - // navigateWithName(context, ProviderAppRoutes.branchDetail, arguments: model.branchs!.data!.serviceProviderBranch![index]); - }); - }, - separatorBuilder: (context, index) { - return 12.height; - }, - itemCount: model.branches!.data!.serviceProviderBranch!.length, - padding: const EdgeInsets.all(12), - ); - } - }, + child: SingleChildScrollView( + child: Container( + width: double.infinity, + height: MediaQuery.of(context).size.height / 1.37, + child: Consumer( + builder: (context, model, _) { + if (model.state == ViewState.busy) { + return const Center(child: CircularProgressIndicator()); + } else { + return model.branches?.data == null + ? const Center(child: Text("No Branch Found")) + : model.branches!.data!.isEmpty + ? Center(child: Text(LocaleKeys.no_branch.tr())) + : ListView.separated( + itemBuilder: (context, index) { + return ProviderDetailsCard( + onCardTapped: () { + navigateWithName(context, AppRoutes.branchDetailPage, arguments: model.branches!.data![index]); + }, + providerImageUrl: MyAssets.bnCar, + title: model.branches!.data![index].branchName ?? "", + providerLocation: model.branches!.data![index].distanceKm.toString() + " KM", + providerName: model.branches!.data![index].serviceProviderName ?? "", + providerRatings: "4.9", + items: model.branches!.data![index].branchServices, + ); + }, + separatorBuilder: (context, index) { + return 12.height; + }, + itemCount: model.branches!.data!.length, + padding: const EdgeInsets.all(12), + ); + } + }, + ), ), ), ), diff --git a/lib/views/dashboard/fragments/providers_fragment.dart b/lib/views/dashboard/fragments/providers_fragment.dart index 235874b..09e6dab 100644 --- a/lib/views/dashboard/fragments/providers_fragment.dart +++ b/lib/views/dashboard/fragments/providers_fragment.dart @@ -43,6 +43,7 @@ class ProvidersFragment extends StatelessWidget { navigateWithName(context, AppRoutes.bookAppointmenServicesView); }, providerImageUrl: MyAssets.bnCar, + title:"", providerLocation: " 3km", providerName: "Al Ahmed Maintenance", providerRatings: "4.9", diff --git a/lib/views/provider/branch_detail_page.dart b/lib/views/provider/branch_detail_page.dart new file mode 100644 index 0000000..6158696 --- /dev/null +++ b/lib/views/provider/branch_detail_page.dart @@ -0,0 +1,208 @@ +import 'package:flutter/material.dart'; +import 'package:mc_common_app/classes/consts.dart'; +import 'package:mc_common_app/extensions/int_extensions.dart'; +import 'package:mc_common_app/extensions/string_extensions.dart'; +import 'package:mc_common_app/generated/locale_keys.g.dart'; +import 'package:mc_common_app/models/services/branch_model.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:mc_common_app/models/services/service_model.dart'; +import 'package:mc_common_app/theme/colors.dart'; +import 'package:mc_common_app/widgets/button/show_fill_button.dart'; +import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; +import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; + +class BranchDetailPage extends StatefulWidget { + BranchModel branchModel; + + BranchDetailPage({required this.branchModel}); + + @override + State createState() => _BranchDetailPageState(); +} + +class _BranchDetailPageState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: CustomAppBar( + title: "Branch Detail", + ), + body: Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Container( + width: double.infinity, + padding: EdgeInsets.all(21), + child: Column( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Image.asset(MyAssets.bnCar), + 12.height, + "${widget.branchModel.branchName} | ${widget.branchModel.serviceProviderName}".toString().toText( + fontSize: 16, + isBold: true, + ), + Row( + children: [ + (LocaleKeys.location.tr() + ":").toText(color: MyColors.lightTextColor, fontSize: 12), + 4.width, + (widget.branchModel.distanceKm.toString() + " km").toText(fontSize: 12, isBold: true), + ], + ), + Row( + children: [ + ("Time" + ":").toText(color: MyColors.lightTextColor, fontSize: 12), + 4.width, + "${widget.branchModel.openTime} - ${widget.branchModel.closeTime}".toText(fontSize: 12, isBold: true), + ], + ), + 2.height, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + "Open Map Location".toText( + fontSize: 12, + isBold: true, + color: MyColors.primaryColor, + isUnderLine: true, + ), + 4.width, + Image.asset( + MyAssets.icRightUpPng, + height: 6, + width: 6, + color: MyColors.primaryColor, + ), + ], + ) + .padding( + EdgeInsets.symmetric(vertical: 6, horizontal: 2), + ) + .onPress( + () {}, + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + "Provider Profile".toText( + fontSize: 12, + isBold: true, + color: MyColors.primaryColor, + isUnderLine: true, + ), + 2.width, + Icon( + Icons.arrow_forward, + size: 12, + color: MyColors.primaryColor, + ), + ], + ) + .padding( + EdgeInsets.symmetric(vertical: 6, horizontal: 2), + ) + .onPress( + () {}, + ), + ], + ), + 20.height, + "Services Offer".toText( + fontSize: 16, + color: MyColors.lightTextColor, + isBold: true, + ), + showServicesList(), + ], + ).toWhiteContainer( + width: double.infinity, + allPading: 12, + ), + ], + ), + ), + ), + ), + ShowFillButton( + title: "Book Appointment", + maxWidth: double.infinity, + margin: EdgeInsets.all(21), + onPressed: () {}, + ).toContainer( + paddingAll: 0, + backgroundColor: Colors.white, + ), + ], + ), + ); + } + + Widget showServicesList() { + return ListView.separated( + itemBuilder: (context, index) { + return ExpansionTile( + tilePadding: EdgeInsets.zero, + title: (widget.branchModel.branchServices![index].serviceDescription ?? "").toText( + fontSize: 16, + isBold: true, + ), + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + showItem("Allowing home service:", (widget.branchModel.branchServices![index].isAllowAppointment ?? false) ? "Yes" : "No", valueColor: Colors.green), + showItem("Home service range", widget.branchModel.branchServices![index].customerLocationRange.toString() + "KM"), + showItem("Charges per KM", widget.branchModel.branchServices![index].customerLocationRange.toString() + "SAR"), + 8.height, + (widget.branchModel.branchServices![index].itemsCount.toString() + "+ services").toText( + fontSize: 12, + isBold: true, + color: MyColors.primaryColor, + isUnderLine: true, + ), + 20.height, + ], + ).onPress(() {}), + ], + onExpansionChanged: (value) { + setState(() { + widget.branchModel.branchServices![index].isExpanded = value; + }); + }, + backgroundColor: Colors.transparent, + collapsedBackgroundColor: Colors.transparent, + initiallyExpanded: widget.branchModel.branchServices![index].isExpanded, + trailing: widget.branchModel.branchServices![index].isExpanded ? Icon(Icons.keyboard_arrow_up) : Icon(Icons.keyboard_arrow_down), + ); + }, + separatorBuilder: (context, index) { + return Divider( + height: 1, + ); + }, + itemCount: widget.branchModel.branchServices!.length, + physics: NeverScrollableScrollPhysics(), + shrinkWrap: true, + ); + } + + Widget showItem(String item, String value, {Color valueColor = Colors.black}) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + item.toText(fontSize: 12, color: MyColors.lightTextColor, isBold: true), + 4.width, + value.toText(fontSize: 12, color: valueColor, isBold: true), + ], + ); + } +}