diff --git a/lib/config/provider_routes.dart b/lib/config/provider_routes.dart index be47b57..bad4a2a 100644 --- a/lib/config/provider_routes.dart +++ b/lib/config/provider_routes.dart @@ -29,10 +29,12 @@ 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/utils/enums.dart'; import 'package:mc_common_app/views/advertisement/ads_detail_view.dart'; import 'package:mc_common_app/views/advertisement/create_ad_view.dart'; import 'package:mc_common_app/views/advertisement/select_ad_type_view.dart'; import 'package:mc_common_app/views/chat/chat_view.dart'; +import 'package:mc_common_app/views/payments/payment_methods_view.dart'; import '../views/dashboard/dashboard_page.dart'; @@ -68,6 +70,10 @@ class ProviderAppRoutes { static const String schedulesList = "/schedulesList"; static const String addSchedule = "/addSchedule"; + // Subscriptions + static const String mySubscriptionsPage = "/mySubscriptionsPage"; + static const String subscriptionsPage = "/subscriptionsPage"; + //Bracnh Duplication static const String matchServices = "/matchServices"; @@ -109,8 +115,9 @@ class ProviderAppRoutes { AppRoutes.sendOfferPage: (context) => const SendOfferPage(), //Subscriptions - AppRoutes.mySubscriptionsPage: (context) => const MySubscriptionsPage(), - AppRoutes.subscriptionsPage: (context) => const SubscriptionsPage(), + mySubscriptionsPage: (context) => const MySubscriptionsPage(), + subscriptionsPage: (context) => const SubscriptionsPage(), + AppRoutes.paymentMethodsView: (context) => PaymentMethodsView(paymentType: ModalRoute.of(context)!.settings.arguments as PaymentTypes), //Services dealerUser: (context) => diff --git a/lib/main.dart b/lib/main.dart index 5082085..8707394 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -20,16 +20,19 @@ import 'package:mc_common_app/repositories/ads_repo.dart'; import 'package:mc_common_app/repositories/appointment_repo.dart'; import 'package:mc_common_app/repositories/chat_repo.dart'; import 'package:mc_common_app/repositories/common_repo.dart'; +import 'package:mc_common_app/repositories/payments_repo.dart'; import 'package:mc_common_app/repositories/provider_repo.dart'; import 'package:mc_common_app/repositories/request_repo.dart'; import 'package:mc_common_app/repositories/user_repo.dart'; import 'package:mc_common_app/services/common_services.dart'; +import 'package:mc_common_app/services/payments_service.dart'; import 'package:mc_common_app/theme/app_theme.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/base_view_model.dart'; import 'package:mc_common_app/view_models/chat_view_model.dart'; +import 'package:mc_common_app/view_models/payment_view_model.dart'; import 'package:mc_common_app/view_models/requests_view_model.dart'; import 'package:mc_common_app/view_models/user_view_model.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; @@ -73,7 +76,8 @@ Future main() async { ), ), ChangeNotifierProvider( - create: (_) => SubscriptionsVM(subscriptionRepo: injector.get()), + create: (_) => + SubscriptionsVM(subscriptionRepo: injector.get()), ), ChangeNotifierProvider( create: (_) => ItemsVM( @@ -114,6 +118,11 @@ Future main() async { requestRepo: injector.get(), ), ), + ChangeNotifierProvider( + create: (_) => PaymentVM( + paymentService: injector.get(), + paymentRepo: injector.get()), + ), ], child: const MyApp(), ).setupLocale()); @@ -135,12 +144,19 @@ class MyApp extends StatelessWidget { injector.get().setAppType(AppType.provider); AppState().setPostParamsModel( PostParamsModel( - languageID: EasyLocalization.of(context)?.locale.languageCode == "ar" ? 1 : 2, + languageID: + EasyLocalization.of(context)?.locale.languageCode == "ar" + ? 1 + : 2, ), ); - ThemeData data = AppTheme.getTheme(isArabic: EasyLocalization.of(context)?.locale.languageCode == "ar"); + ThemeData data = AppTheme.getTheme( + isArabic: + EasyLocalization.of(context)?.locale.languageCode == "ar"); return MaterialApp( - theme: AppTheme.getTheme(isArabic: EasyLocalization.of(context)?.locale.languageCode == "ar"), + theme: AppTheme.getTheme( + isArabic: + EasyLocalization.of(context)?.locale.languageCode == "ar"), debugShowCheckedModeBanner: false, localizationsDelegates: context.localizationDelegates, supportedLocales: context.supportedLocales, diff --git a/lib/view_models/items_view_model.dart b/lib/view_models/items_view_model.dart index 036a075..d7bda4d 100644 --- a/lib/view_models/items_view_model.dart +++ b/lib/view_models/items_view_model.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:car_provider_app/repositories/items_repo.dart'; +import 'package:flutter/cupertino.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/services/common_services.dart'; @@ -20,8 +21,8 @@ class ItemsVM extends BaseVM { //Items ItemModel? serviceItems; - Future selectFile() async { - File? file = await commonServices.pickFile(fileType: FileType.image); + Future selectFile(BuildContext context) async { + File? file = await commonServices.pickFile(context,fileType: FileType.image); if (file != null) { int sizeInBytes = file.lengthSync(); diff --git a/lib/view_models/service_view_model.dart b/lib/view_models/service_view_model.dart index e2063f6..fceaf70 100644 --- a/lib/view_models/service_view_model.dart +++ b/lib/view_models/service_view_model.dart @@ -240,6 +240,7 @@ import 'dart:io'; import 'package:car_provider_app/repositories/branch_repo.dart'; import 'package:file_picker/file_picker.dart'; +import 'package:flutter/cupertino.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'; @@ -297,8 +298,9 @@ class ServiceVM extends BaseVM { setState(ViewState.idle); } - Future selectFile(int index) async { + Future selectFile(BuildContext context,int index) async { final File? file = await commonServices.pickFile( + context, fileType: FileType.custom, allowedExtensions: ['png', 'pdf', 'jpeg'], ); @@ -348,12 +350,15 @@ class ServiceVM extends BaseVM { Future getAllCountriesList( BranchDetailModel? branchData, String countryCode) async { + cities = null; + country = null; setState(ViewState.busy); resetValues(); country = await commonRepo.getAllCountries(); country!.data?.forEach((element) { if (branchData != null && branchData.id != null) { if (element.id == branchData.countryID) { + countryId = element.id ?? -1; countryValue = DropValue( element.id ?? 0, countryCode == "SA" @@ -382,10 +387,10 @@ class ServiceVM extends BaseVM { Future getAllCities( BranchDetailModel? branchData, String countryCode) async { setState(ViewState.busy); - citiesDropList=[]; + citiesDropList = []; cities = null; cityId = -1; - cityValue=null; + cityValue = null; cities = await commonRepo.getAllCites(countryId.toString()); cities!.data?.forEach((element) { if (branchData != null && branchData.id != null) { @@ -512,7 +517,7 @@ class ServiceVM extends BaseVM { Future fetchProviderServices(String branchID, String categoryId) async { servicesDropList = []; - services=null; + services = null; setState(ViewState.busy); services = await branchRepo.fetchProviderServices(branchID, categoryId); diff --git a/lib/views/dashboard/dashboard_page.dart b/lib/views/dashboard/dashboard_page.dart index 10f09b3..612704a 100644 --- a/lib/views/dashboard/dashboard_page.dart +++ b/lib/views/dashboard/dashboard_page.dart @@ -55,16 +55,16 @@ class _DashboardPageState extends State { context.read().getBranchAndServices(); AdVM adVm = Provider.of(context, listen: false); AppointmentsVM appointmentsVM = - Provider.of(context, listen: false); + Provider.of(context, listen: false); if (appointmentsVM.myAppointments.isEmpty) { await appointmentsVM.getProviderMyAppointments({ "ServiceProviderID": injector - .get() - .getUser - .data - ?.userInfo - ?.providerId - .toString() ?? + .get() + .getUser + .data + ?.userInfo + ?.providerId + .toString() ?? "0" }); } @@ -75,7 +75,8 @@ class _DashboardPageState extends State { if (adVm.exploreAds.isEmpty) { await adVm.getExploreAds(); - } if (adVm.vehicleTypes.isEmpty) { + } + if (adVm.vehicleTypes.isEmpty) { await adVm.getVehicleTypes(); } @@ -88,7 +89,6 @@ class _DashboardPageState extends State { } // await chatVM.buildHubConnection(context); - } @override @@ -98,11 +98,17 @@ class _DashboardPageState extends State { onBackButtonTapped: () { dashboardVM.updateIndex(2); }, + onRefresh: () async { + context.read().getBranchAndServices(); + }, ), BranchAppointmentFragment( onBackButtonTapped: () { dashboardVM.updateIndex(2); }, + onRefresh: () async { + context.read().getBranchAndServices(); + }, ), HomeFragment( onTap: () { @@ -120,7 +126,11 @@ class _DashboardPageState extends State { dashboardVM.updateIndex(2); }, ), - const MyRequestsFragment(), + MyRequestsFragment( + onBackButtonTapped: () { + dashboardVM.updateIndex(2); + }, + ), ]; return Scaffold( diff --git a/lib/views/dashboard/fragments/branch_appointment_fragment.dart b/lib/views/dashboard/fragments/branch_appointment_fragment.dart index e2d9cc6..52cd3c3 100644 --- a/lib/views/dashboard/fragments/branch_appointment_fragment.dart +++ b/lib/views/dashboard/fragments/branch_appointment_fragment.dart @@ -24,10 +24,14 @@ import 'package:flutter_svg/flutter_svg.dart'; class BranchAppointmentFragment extends StatelessWidget { bool isNeedAppBar; VoidCallback onBackButtonTapped; + RefreshCallback onRefresh; - BranchAppointmentFragment( - {Key? key, this.isNeedAppBar = true, required this.onBackButtonTapped}) - : super(key: key); + BranchAppointmentFragment({ + Key? key, + this.isNeedAppBar = true, + required this.onBackButtonTapped, + required this.onRefresh, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -71,93 +75,96 @@ class BranchAppointmentFragment extends StatelessWidget { 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)), + return RefreshIndicator( + onRefresh: onRefresh, + child: 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, + ), ), - 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, + 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, ), - 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), - ], + "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), - ); + 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), + ), + ); } }, ), diff --git a/lib/views/dashboard/fragments/home_fragment.dart b/lib/views/dashboard/fragments/home_fragment.dart index 7d24f08..7feb6e7 100644 --- a/lib/views/dashboard/fragments/home_fragment.dart +++ b/lib/views/dashboard/fragments/home_fragment.dart @@ -64,97 +64,95 @@ class HomeFragment extends StatelessWidget { height: double.infinity, child: RefreshIndicator( onRefresh: onRefresh, - child: SingleChildScrollView( - child: Column( - children: [ - ViewAllWidget( - title: 'Upcoming Appointment', - subTitle: 'View All', - onSubtitleTapped: () {}, - ).horPaddingMain(), - // const AppointmentSliderWidget().horPaddingMain(), - CustomerAppointmentSliderWidget( - myUpComingAppointments: - context.read().myUpComingAppointments, - isNeedToShowEmptyMessage: true, - onAppointmentClick: (){ - // navigateWithName( - // context, ProviderAppRoutes.appointment, - // arguments: branches[index]); - }, - ), - 21.height, - ViewAllWidget( - title: 'My Branches', - subTitle: 'View All', - onSubtitleTapped: () {}, - ).horPaddingMain(), - const ServiceProviderWidget().horPaddingMain(), - Consumer( - builder: (BuildContext context, AdVM adVM, Widget? child) { - if (adVM.state == ViewState.busy) { - return const Center(child: CircularProgressIndicator()); - } else { - return Column( - children: [ - if (adVM.myActiveAdsForHome.isNotEmpty) ...[ - Column( - children: [ - 15.height, - ViewAllWidget( - title: "My Active Ads", - subTitle: "View All", - onSubtitleTapped: () { - // context.read().onNavbarTapped(3); - // context.read().updateIsExploreAds(false); - }, - ).horPaddingMain(), - BuildAdsList( - shouldShowAdStatus: true, - isAdsFragment: false, - adsList: adVM.myActiveAdsForHome, - scrollPhysics: - const NeverScrollableScrollPhysics(), - ), - ], - ) - ], - if (adVM.exploreAds.isNotEmpty) ...[ - Column( - children: [ - 15.height, - ViewAllWidget( - title: "My Recommended Ads", - subTitle: "View All", - onSubtitleTapped: () { - // context.read().onNavbarTapped(3); - // context.read().updateIsExploreAds(true); - // context.read().applyFilterOnExploreAds(index: 0); - }, - ).horPaddingMain(), - BuildAdsList( - shouldShowAdStatus: false, - adsList: adVM.exploreAds.length >= 3 - ? adVM.exploreAds.take(3).toList() - : adVM.exploreAds, - isAdsFragment: false, - scrollPhysics: - const NeverScrollableScrollPhysics(), - ), - ], - ) - ] + child: ListView( + children: [ + ViewAllWidget( + title: 'Upcoming Appointment', + subTitle: 'View All', + onSubtitleTapped: () {}, + ).horPaddingMain(), + // const AppointmentSliderWidget().horPaddingMain(), + CustomerAppointmentSliderWidget( + myUpComingAppointments: + context.read().myUpComingAppointments, + isNeedToShowEmptyMessage: true, + onAppointmentClick: () { + // navigateWithName( + // context, ProviderAppRoutes.appointment, + // arguments: branches[index]); + }, + ), + 21.height, + ViewAllWidget( + title: 'My Branches', + subTitle: 'View All', + onSubtitleTapped: () {}, + ).horPaddingMain(), + const ServiceProviderWidget().horPaddingMain(), + Consumer( + builder: (BuildContext context, AdVM adVM, Widget? child) { + if (adVM.state == ViewState.busy) { + return const Center(child: CircularProgressIndicator()); + } else { + return Column( + children: [ + if (adVM.myActiveAdsForHome.isNotEmpty) ...[ + Column( + children: [ + 15.height, + ViewAllWidget( + title: "My Active Ads", + subTitle: "View All", + onSubtitleTapped: () { + // context.read().onNavbarTapped(3); + // context.read().updateIsExploreAds(false); + }, + ).horPaddingMain(), + BuildAdsList( + shouldShowAdStatus: true, + isAdsFragment: false, + adsList: adVM.myActiveAdsForHome, + scrollPhysics: + const NeverScrollableScrollPhysics(), + ), + ], + ) ], - ); - } - }, - ), - 21.height, - // const AdWidget( - // count: 4, - // ), - ], - ), + if (adVM.exploreAds.isNotEmpty) ...[ + Column( + children: [ + 15.height, + ViewAllWidget( + title: "My Recommended Ads", + subTitle: "View All", + onSubtitleTapped: () { + // context.read().onNavbarTapped(3); + // context.read().updateIsExploreAds(true); + // context.read().applyFilterOnExploreAds(index: 0); + }, + ).horPaddingMain(), + BuildAdsList( + shouldShowAdStatus: false, + adsList: adVM.exploreAds.length >= 3 + ? adVM.exploreAds.take(3).toList() + : adVM.exploreAds, + isAdsFragment: false, + scrollPhysics: + const NeverScrollableScrollPhysics(), + ), + ], + ) + ] + ], + ); + } + }, + ), + 21.height, + // const AdWidget( + // count: 4, + // ), + ], ), ), ), diff --git a/lib/views/dashboard/fragments/my_requests_fragment.dart b/lib/views/dashboard/fragments/my_requests_fragment.dart index 04e9cf3..e6e2f8f 100644 --- a/lib/views/dashboard/fragments/my_requests_fragment.dart +++ b/lib/views/dashboard/fragments/my_requests_fragment.dart @@ -15,49 +15,65 @@ import 'package:easy_localization/easy_localization.dart'; class MyRequestsFragment extends StatelessWidget { final bool isNeedAppBar; + VoidCallback onBackButtonTapped; - const MyRequestsFragment({super.key, this.isNeedAppBar = true}); + MyRequestsFragment( + {super.key, this.isNeedAppBar = true, required this.onBackButtonTapped}); @override Widget build(BuildContext context) { return Scaffold( - appBar: !isNeedAppBar ? null : CustomAppBar(title: LocaleKeys.myServiceBranches.tr()), + appBar: !isNeedAppBar + ? null + : CustomAppBar( + title: LocaleKeys.myServiceBranches.tr(), + onBackButtonTapped: onBackButtonTapped, + ), body: Container( color: MyColors.backgroundColor, width: double.infinity, height: double.infinity, - child: Consumer(builder: (BuildContext context, RequestsVM requestsVM, Widget? child) { + child: Consumer(builder: + (BuildContext context, RequestsVM requestsVM, Widget? child) { return Column( children: [ 16.height, FiltersList( filterList: requestsVM.requestsTypeFilterOptions, onFilterTapped: (index, selectedFilterId) { - requestsVM.applyFilterOnRequestsVM(requestsTypeEnum: selectedFilterId.toRequestTypeStatusEnum()); + requestsVM.applyFilterOnRequestsVM( + requestsTypeEnum: + selectedFilterId.toRequestTypeStatusEnum()); }, ), 8.height, Expanded( child: RefreshIndicator( - onRefresh: () async => await requestsVM.getRequests(isNeedToRebuild: true, appType: AppType.provider), + onRefresh: () async => await requestsVM.getRequests( + isNeedToRebuild: true, appType: AppType.provider), child: requestsVM.state == ViewState.busy ? const Center(child: CircularProgressIndicator()) : requestsVM.myFilteredRequests.isEmpty ? Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - "No Requests to show.".toText(fontSize: 16, color: MyColors.lightTextColor), + "No Requests to show.".toText( + fontSize: 16, color: MyColors.lightTextColor), ], ) : ListView.separated( itemBuilder: (context, index) { - return RequestItem(request: requestsVM.myFilteredRequests[index], appType: AppType.provider, requestIndex: index); + return RequestItem( + request: requestsVM.myFilteredRequests[index], + appType: AppType.provider, + requestIndex: index); }, separatorBuilder: (context, index) { return 16.height; }, itemCount: requestsVM.myFilteredRequests.length, - padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16, top: 8), + padding: const EdgeInsets.only( + left: 16, right: 16, bottom: 16, top: 8), ), )) ], diff --git a/lib/views/dashboard/widget/drawer_widget.dart b/lib/views/dashboard/widget/drawer_widget.dart index 86d9593..e366ac4 100644 --- a/lib/views/dashboard/widget/drawer_widget.dart +++ b/lib/views/dashboard/widget/drawer_widget.dart @@ -35,8 +35,14 @@ class _CustomDrawerState extends State { builder: (context) => AlertDialog( content: const Text("Choose image source"), actions: [ - TextButton(child: const Text("Camera"), onPressed: () => widget.dashboardVM.pickImageFromPhone(context, 0)), - TextButton(child: const Text("Gallery"), onPressed: () => widget.dashboardVM.pickImageFromPhone(context, 1)), + TextButton( + child: const Text("Camera"), + onPressed: () => + widget.dashboardVM.pickImageFromPhone(context, 0)), + TextButton( + child: const Text("Gallery"), + onPressed: () => + widget.dashboardVM.pickImageFromPhone(context, 1)), ], ), ); @@ -54,7 +60,13 @@ class _CustomDrawerState extends State { height: 200, color: MyColors.darkPrimaryColor.withOpacity(0.01), child: Image.network( - ApiConsts.baseUrlServices + AppState().getUser.data!.userInfo!.userImageUrl.toString(), + ApiConsts.baseUrlServices + + AppState() + .getUser + .data! + .userInfo! + .userImageUrl + .toString(), ), ), Positioned( @@ -94,11 +106,16 @@ class _CustomDrawerState extends State { color: Colors.red, ).onPress(() async { Utils.showLoading(context); - ImageResponse response = await widget.dashboardVM.updateUserImage(""); + ImageResponse response = + await widget.dashboardVM.updateUserImage(""); if (response.messageStatus == 1) { Utils.showToast("Image is Deleted"); setState(() { - AppState().getUser.data!.userInfo!.userImageUrl = response.data; + AppState() + .getUser + .data! + .userInfo! + .userImageUrl = response.data; }); } Utils.hideLoading(context); @@ -127,7 +144,12 @@ class _CustomDrawerState extends State { fontSize: 20, letterSpacing: -1.44, ), - AppState().getUser.data!.userInfo!.roleName!.toText(fontSize: 10), + AppState() + .getUser + .data! + .userInfo! + .roleName! + .toText(fontSize: 10), ], ), ), @@ -144,12 +166,21 @@ class _CustomDrawerState extends State { ), ), ListTile( - leading: SvgPicture.asset(MyAssets.nextIcon, color: MyColors.darkPrimaryColor), + leading: SvgPicture.asset(MyAssets.nextIcon, + color: MyColors.darkPrimaryColor), title: LocaleKeys.defineLicences.tr().toText(fontSize: 12), onTap: () { navigateWithName(context, ProviderAppRoutes.defineLicense); }, ), + ListTile( + leading: SvgPicture.asset(MyAssets.nextIcon, + color: MyColors.darkPrimaryColor), + title: "Subscriptions".toText(fontSize: 12), + onTap: () { + navigateWithName(context, ProviderAppRoutes.mySubscriptionsPage); + }, + ), ListTile( leading: Image.asset( MyAssets.icWorldPng, @@ -159,7 +190,8 @@ class _CustomDrawerState extends State { ), title: LocaleKeys.english.tr().toText(fontSize: 12), onTap: () { - if (EasyLocalization.of(context)?.currentLocale?.countryCode == "SA") { + if (EasyLocalization.of(context)?.currentLocale?.countryCode == + "SA") { context.setLocale(const Locale("en", "US")); } else { context.setLocale(const Locale('ar', 'SA')); diff --git a/lib/views/location/pick_location_page.dart b/lib/views/location/pick_location_page.dart index 6c5900d..742bdf0 100644 --- a/lib/views/location/pick_location_page.dart +++ b/lib/views/location/pick_location_page.dart @@ -9,7 +9,7 @@ import 'package:car_provider_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; -import 'package:geocoding/geocoding.dart'; + import 'package:permission_handler/permission_handler.dart'; import 'map_selection_widget.dart'; diff --git a/lib/views/settings/branch/branch_detail_page.dart b/lib/views/settings/branch/branch_detail_page.dart index 372d5c6..27bb5bd 100644 --- a/lib/views/settings/branch/branch_detail_page.dart +++ b/lib/views/settings/branch/branch_detail_page.dart @@ -76,11 +76,14 @@ class BranchDetailPage extends StatelessWidget { Row( children: [ Expanded( - child: titleWidget(MyAssets.icBranches, LocaleKeys.branchInfo.tr()), + child: titleWidget(MyAssets.icBranches, + LocaleKeys.branchInfo.tr()), ), IconButton( onPressed: () { - navigateWithName(context, ProviderAppRoutes.defineBranch, arguments: branchData); + navigateWithName( + context, ProviderAppRoutes.defineBranch, + arguments: branchData); }, icon: SvgPicture.asset(MyAssets.icEdit), ) @@ -88,11 +91,17 @@ class BranchDetailPage extends StatelessWidget { ), Column( children: [ - showData("${LocaleKeys.country.tr()}:", "branchData.countryName".toString()), - showData("${LocaleKeys.city.tr()}:", "branchData.cityName".toString()), - showData("${LocaleKeys.branchName.tr()}:", branchData.branchName.toString()), - showData("${LocaleKeys.branchDescription.tr()}:", branchData.branchDescription.toString()), - showData("${LocaleKeys.address.tr()}:", branchData.address.toString()), + showData("${LocaleKeys.country.tr()}:", + branchData.countryName.toString()), + showData("${LocaleKeys.city.tr()}:", + branchData.cityName.toString()), + showData("${LocaleKeys.branchName.tr()}:", + branchData.branchName.toString()), + showData( + "${LocaleKeys.branchDescription.tr()}:", + branchData.branchDescription.toString()), + showData("${LocaleKeys.address.tr()}:", + branchData.address.toString()), ], ), ], @@ -101,7 +110,8 @@ class BranchDetailPage extends StatelessWidget { Container( width: double.infinity, color: MyColors.darkIconColor, - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 20, vertical: 8), child: Row( children: [ const Icon( @@ -125,7 +135,9 @@ class BranchDetailPage extends StatelessWidget { ], ), ).onPress(() { - navigateWithName(context, ProviderAppRoutes.schedulesList, arguments: branchData.id.toString()); + navigateWithName( + context, ProviderAppRoutes.schedulesList, + arguments: branchData.id.toString()); }), Row( crossAxisAlignment: CrossAxisAlignment.center, @@ -152,7 +164,8 @@ class BranchDetailPage extends StatelessWidget { backgroundColor: MyColors.darkWhiteColor, width: double.infinity, paddingAll: 20, - margin: const EdgeInsets.only(left: 20, right: 20, top: 20), + margin: + const EdgeInsets.only(left: 20, right: 20, top: 20), ) .onPress(() { navigateWithName( @@ -170,12 +183,17 @@ class BranchDetailPage extends StatelessWidget { itemBuilder: (context, pIndex) { return InkWell( onTap: () { - categories[pIndex].branchId = branchData.id.toString(); - categories[pIndex].branchName = branchData.branchName.toString(); - navigateWithName(context, ProviderAppRoutes.servicesList, arguments: categories[pIndex]); + categories[pIndex].branchId = + branchData.id.toString(); + categories[pIndex].branchName = + branchData.branchName.toString(); + navigateWithName( + context, ProviderAppRoutes.servicesList, + arguments: categories[pIndex]); }, child: Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Padding( @@ -189,12 +207,19 @@ class BranchDetailPage extends StatelessWidget { 8.width, Expanded( child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.start, children: [ Row( children: [ - categories[pIndex].categoryName.toString().toText(fontSize: 16, isBold: true), + categories[pIndex] + .categoryName + .toString() + .toText( + fontSize: 16, + isBold: true), // Padding( // padding: const EdgeInsets.all(4.0), // child: SvgPicture.asset( @@ -204,26 +229,46 @@ class BranchDetailPage extends StatelessWidget { // ), // ), ], - mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, ), Row( children: [ Expanded( child: ListView.builder( - itemBuilder: (context, index) { + itemBuilder: + (context, index) { return Container( - child: (EasyLocalization.of(context)?.currentLocale?.countryCode == "SA" - ? categories[pIndex].services![index].serviceDescriptionN.toString() - : categories[pIndex].services![index].serviceDescription.toString()) + child: (EasyLocalization.of( + context) + ?.currentLocale + ?.countryCode == + "SA" + ? categories[ + pIndex] + .services![ + index] + .serviceDescriptionN + .toString() + : categories[ + pIndex] + .services![ + index] + .serviceDescription + .toString()) .toText( fontSize: 12, - color: MyColors.lightTextColor, + color: MyColors + .lightTextColor, isBold: true, ), ); }, - itemCount: categories[pIndex].services?.length, - physics: const NeverScrollableScrollPhysics(), + itemCount: categories[pIndex] + .services + ?.length, + physics: + const NeverScrollableScrollPhysics(), shrinkWrap: true, padding: EdgeInsets.zero, ), @@ -236,15 +281,18 @@ class BranchDetailPage extends StatelessWidget { ), ), ], - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: + MainAxisAlignment.end, + crossAxisAlignment: + CrossAxisAlignment.end, ) ], )), ], ).toContainer( width: double.infinity, - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 8), isShadowEnabled: true, ), ); @@ -253,7 +301,8 @@ class BranchDetailPage extends StatelessWidget { physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, padding: const EdgeInsets.all(20), - separatorBuilder: (BuildContext context, int index) { + separatorBuilder: + (BuildContext context, int index) { return 12.height; }, ), @@ -278,7 +327,8 @@ class BranchDetailPage extends StatelessWidget { txtColor: MyColors.darkPrimaryColor, isFilled: false, onPressed: () { - navigateWithName(context, ProviderAppRoutes.dealerUser, arguments: branchData.id.toString()); + navigateWithName(context, ProviderAppRoutes.dealerUser, + arguments: branchData.id.toString()); }, ), ), diff --git a/lib/views/settings/branch/branch_list_page.dart b/lib/views/settings/branch/branch_list_page.dart index ac16203..dab6a8c 100644 --- a/lib/views/settings/branch/branch_list_page.dart +++ b/lib/views/settings/branch/branch_list_page.dart @@ -27,8 +27,14 @@ import 'package:provider/provider.dart'; class BranchListPage extends StatelessWidget { bool isNeedAppBar; VoidCallback onBackButtonTapped; + RefreshCallback onRefresh; - BranchListPage({Key? key, this.isNeedAppBar = true, required this.onBackButtonTapped}) : super(key: key); + BranchListPage( + {Key? key, + this.isNeedAppBar = true, + required this.onRefresh, + required this.onBackButtonTapped}) + : super(key: key); @override Widget build(BuildContext context) { @@ -56,7 +62,9 @@ class BranchListPage extends StatelessWidget { Padding( padding: const EdgeInsets.only(left: 21, right: 21, top: 21), child: RoleTypeTab( - context.watch().selectedBranchStatus == 3 ? 0 : context.watch().selectedBranchStatus, + context.watch().selectedBranchStatus == 3 + ? 0 + : context.watch().selectedBranchStatus, [ DropValue(3, "Active", ""), DropValue(1, "Requested", ""), @@ -74,95 +82,130 @@ class BranchListPage extends StatelessWidget { } else { List branches = []; if (model.branches!.data != null) { - branches = model.branches!.data!.serviceProviderBranch!.where((element) => model.selectedBranchStatus == element.statusId).toList(); + 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)), + return RefreshIndicator( + onRefresh: onRefresh, + child: 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, + ), ), - 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, + 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, ), - 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, ), - ), - LocaleKeys.tapToEdit.tr().toText(fontSize: 10, color: MyColors.grey70Color), - ], + LocaleKeys.tapToEdit.tr().toText( + fontSize: 10, + color: MyColors.grey70Color), + ], + ), + ), + 12.width, + IconButton( + onPressed: () async { + Utils.showLoading(context); + MResponse res = await model.updateBranch( + branches[index].id ?? 0, + branches[index].branchName ?? "", + branches[index].branchDescription ?? + "", + branches[index].cityId.toString(), + branches[index].address ?? "", + branches[index].latitude.toString(), + branches[index].longitude.toString(), + isNeedToDelete: false); + Utils.hideLoading(context); + if (res.messageStatus == 1) { + Utils.showToast( + LocaleKeys.branch_deleted.tr()); + model.setState(ViewState.idle); + } else { + Utils.showToast(res.message ?? ""); + } + }, + icon: const Icon(Icons.delete), + color: Colors.red, + ), + const Icon( + Icons.arrow_forward_rounded, + size: 16, ), - ), - 12.width, - IconButton( - onPressed: () async { - Utils.showLoading(context); - MResponse res = await model.updateBranch(branches[index].id ?? 0, branches[index].branchName ?? "", branches[index].branchDescription ?? "", - branches[index].cityId.toString(), branches[index].address ?? "", branches[index].latitude.toString(), branches[index].longitude.toString(), - isNeedToDelete: false); - Utils.hideLoading(context); - if (res.messageStatus == 1) { - Utils.showToast(LocaleKeys.branch_deleted.tr()); - model.setState(ViewState.idle); - } else { - Utils.showToast(res.message ?? ""); - } - }, - icon: const Icon(Icons.delete), - color: Colors.red, - ), - const Icon( - Icons.arrow_forward_rounded, - size: 16, - ), - ], - ).toContainer().onPress(() async { - branches[index].countryID = model.branches!.data!.countryID; - branches[index].countryName = model.branches!.data!.countryName; - navigateWithName(context, ProviderAppRoutes.branchDetail, arguments: branches[index]); - }); - }, - separatorBuilder: (context, index) { - return 12.height; - }, - itemCount: branches.length, - padding: const EdgeInsets.all(12), - ); + ], + ).toContainer().onPress(() async { + branches[index].countryID = + model.branches!.data!.countryID; + branches[index].countryName = + model.branches!.data!.countryName; + navigateWithName( + context, ProviderAppRoutes.branchDetail, + arguments: branches[index]); + }); + }, + separatorBuilder: (context, index) { + return 12.height; + }, + itemCount: branches.length, + padding: const EdgeInsets.all(12), + ), + ); } }, ), diff --git a/lib/views/settings/branch/define_branch_page.dart b/lib/views/settings/branch/define_branch_page.dart index c92cd14..2ab44dc 100644 --- a/lib/views/settings/branch/define_branch_page.dart +++ b/lib/views/settings/branch/define_branch_page.dart @@ -62,6 +62,7 @@ class DefineBranchPage extends StatelessWidget { ?.countryCode ?? "SA"); }, + isSelectAble: branchData == null ? true : false, list: model.countryDropList, dropdownValue: model.countryValue, hint: "${LocaleKeys.chooseCountry.tr()}*", @@ -122,7 +123,7 @@ class DefineBranchPage extends StatelessWidget { PickLocationPage( onPickAddress: (double latitude, double longitude, String address) { - print("tesssgngl "+address); + print("tesssgngl " + address); model.latitude = latitude; model.longitude = longitude; model.address = address; diff --git a/lib/views/settings/define_license_page.dart b/lib/views/settings/define_license_page.dart index 7c4bec7..04ecb3d 100644 --- a/lib/views/settings/define_license_page.dart +++ b/lib/views/settings/define_license_page.dart @@ -8,7 +8,8 @@ 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/general_models/m_response.dart'; import 'package:mc_common_app/theme/colors.dart'; -import 'package:mc_common_app/utils/AppPermissionHandler.dart'; +import 'package:mc_common_app/utils/app_permission_handler.dart'; + import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/utils.dart'; import 'package:mc_common_app/widgets/button/show_fill_button.dart'; @@ -144,7 +145,7 @@ class _DefineLicensePageState extends State { InkWell( onTap: () async { bool isPermissionsAvailable = await requestPermissionGranted(context, Permission.storage); - if (isPermissionsAvailable) model.selectFile(index); + if (isPermissionsAvailable) model.selectFile(context,index); }, child: Container( width: double.infinity, diff --git a/lib/views/settings/schedule/add_schedules_page.dart b/lib/views/settings/schedule/add_schedules_page.dart index c8165b1..645efa1 100644 --- a/lib/views/settings/schedule/add_schedules_page.dart +++ b/lib/views/settings/schedule/add_schedules_page.dart @@ -334,12 +334,13 @@ class AddSchedulesPage extends StatelessWidget { context.read().getSchedules(scheduleData.branchId ?? ""); pop(context); } else { - Utils.showToast( - "Something went wrong while adding services in schedule"); + Utils.showToast(servicesResponse.message ?? ""); + context.read().getSchedules(scheduleData.branchId ?? ""); + pop(context); } } else { Utils.hideLoading(context); - Utils.showToast("Something went wrong"); + Utils.showToast(scheduleResponse.message??""); } } diff --git a/lib/views/settings/services/create_item_page.dart b/lib/views/settings/services/create_item_page.dart index 252a216..b5ce762 100644 --- a/lib/views/settings/services/create_item_page.dart +++ b/lib/views/settings/services/create_item_page.dart @@ -7,7 +7,7 @@ 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'; -import 'package:mc_common_app/utils/AppPermissionHandler.dart'; +import 'package:mc_common_app/utils/app_permission_handler.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'; @@ -130,7 +130,7 @@ class _CreateItemPageState extends State { onTap: () async { bool isPermissionsAvailable = await requestPermissionGranted(context, Permission.storage); if (isPermissionsAvailable && model != null) { - itemImage = await model!.selectFile() ?? ""; + itemImage = await model!.selectFile(context) ?? ""; setState(() {}); } }, diff --git a/lib/views/subscriptions/my_subscritions_page.dart b/lib/views/subscriptions/my_subscritions_page.dart index 7b2ac1f..146ebda 100644 --- a/lib/views/subscriptions/my_subscritions_page.dart +++ b/lib/views/subscriptions/my_subscritions_page.dart @@ -1,11 +1,19 @@ +import 'package:car_provider_app/config/provider_routes.dart'; import 'package:car_provider_app/view_models/subscriptions_view_model.dart'; +import 'package:car_provider_app/views/subscriptions/sheet/select_package_sheet.dart'; import 'package:car_provider_app/views/subscriptions/widget/subscriptions_card.dart'; import 'package:flutter/material.dart'; import 'package:mc_common_app/classes/app_state.dart'; +import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/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/payment_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'; class MySubscriptionsPage extends StatelessWidget { @@ -13,7 +21,8 @@ class MySubscriptionsPage extends StatelessWidget { @override Widget build(BuildContext context) { - context.read().getMySubscriptions(AppState().getUser.data?.userInfo?.providerId.toString() ?? ""); + context.read().getMySubscriptions( + AppState().getUser.data?.userInfo?.providerId.toString() ?? ""); return Scaffold( appBar: const CustomAppBar( title: "My Subscriptions", @@ -21,33 +30,70 @@ class MySubscriptionsPage extends StatelessWidget { body: SizedBox( width: double.infinity, height: double.infinity, - child: Consumer(builder: (context, model, _) { - return model.state == ViewState.busy - ? const Center(child: CircularProgressIndicator()) - : SingleChildScrollView( - child: Column( - children: [ - 21.height, - ListView.separated( - itemBuilder: (BuildContext context, int index) { - return SubscriptionsCard( - model.allSubscriptions.data![index], - isSubscribed: model.allSubscriptions.data![index].isSubscribed ?? false, - backgroundColor: MyColors.darkIconColor, - ); - }, - separatorBuilder: (BuildContext context, int index) { - return 21.height; - }, - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: model.allSubscriptions.data!.length, - ), - 21.height, - ], - ), - ); - }), + child: Column( + children: [ + Expanded( + child: Consumer(builder: (context, model, _) { + return model.state == ViewState.busy + ? const Center(child: CircularProgressIndicator()) + : SingleChildScrollView( + child: Column( + children: [ + 21.height, + ListView.separated( + itemBuilder: (BuildContext context, int index) { + return SubscriptionsCard( + model.allSubscriptions.data![index], + isSubscribed: model.allSubscriptions + .data![index].isSubscribed ?? + false, + backgroundColor: MyColors.darkIconColor, + onRenewSubscriptionClick: () { + context + .read() + .updateOrderProviderSubscriptionId( + id: model.allSubscriptions + .data![index].id ?? + 0); + navigateWithName( + context, + AppRoutes.paymentMethodsView, + arguments: PaymentTypes.subscription, + ); + }, + ).onPress( + () { + showMyBottomSheet(context, + child: const SelectPackageSheet()); + }, + ); + }, + separatorBuilder: + (BuildContext context, int index) { + return 21.height; + }, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: model.allSubscriptions.data!.length, + ), + 21.height, + ], + ), + ); + }), + ), + 21.height, + ShowFillButton( + title: "Modify Package", + maxWidth: double.infinity, + margin: const EdgeInsets.symmetric(horizontal: 21), + onPressed: () { + navigateWithName(context, ProviderAppRoutes.subscriptionsPage); + }, + ), + 21.height, + ], + ), ), ); } diff --git a/lib/views/subscriptions/subscriptions_page.dart b/lib/views/subscriptions/subscriptions_page.dart index bbfa64b..f70bad0 100644 --- a/lib/views/subscriptions/subscriptions_page.dart +++ b/lib/views/subscriptions/subscriptions_page.dart @@ -1,10 +1,13 @@ import 'package:car_provider_app/view_models/subscriptions_view_model.dart'; import 'package:car_provider_app/views/subscriptions/widget/subscriptions_card.dart'; import 'package:flutter/material.dart'; +import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart'; import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/enums.dart'; +import 'package:mc_common_app/utils/navigator.dart'; +import 'package:mc_common_app/view_models/payment_view_model.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/tab/menu_tabs.dart'; @@ -47,6 +50,14 @@ class SubscriptionsPage extends StatelessWidget { return SubscriptionsCard( model.tempSubscriptions[index], isSubscribed: model.tempSubscriptions[index].isSubscribed ?? false, + onRenewSubscriptionClick: () { + context.read().updateOrderProviderSubscriptionId(id: model.tempSubscriptions[index].id??0); + navigateWithName( + context, + AppRoutes.paymentMethodsView, + arguments: PaymentTypes.subscription, + ); + }, ); }, separatorBuilder: (BuildContext context, int index) { diff --git a/lib/views/subscriptions/widget/subscriptions_card.dart b/lib/views/subscriptions/widget/subscriptions_card.dart index bf4fb82..6dcc91d 100644 --- a/lib/views/subscriptions/widget/subscriptions_card.dart +++ b/lib/views/subscriptions/widget/subscriptions_card.dart @@ -1,4 +1,3 @@ - import 'package:flutter/material.dart'; import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart'; @@ -7,123 +6,142 @@ import 'package:mc_common_app/theme/colors.dart'; import 'package:mc_common_app/utils/date_helper.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; - class SubscriptionsCard extends StatelessWidget { Subscription subscription; bool isSubscribed; Color? backgroundColor; late Color textColor; + Function onRenewSubscriptionClick; - SubscriptionsCard(this.subscription, {Key? key, this.isSubscribed = false, this.backgroundColor}) : super(key: key); + SubscriptionsCard(this.subscription, + {Key? key, + this.isSubscribed = false, + this.backgroundColor, + required this.onRenewSubscriptionClick}) + : super(key: key); @override Widget build(BuildContext context) { textColor = backgroundColor == null ? Colors.black : Colors.white; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Expanded( - child: subscription.name.toString().toText( - fontSize: 18, - color: textColor, - ), - ), - if (isSubscribed) - Row( - children: [ - Container( - color: MyColors.white, - padding: const EdgeInsets.all(2), - child: const Icon( - Icons.done, - size: 8, - color: MyColors.primaryColor, + return InkWell( + onTap: isSubscribed + ? null + : () { + onRenewSubscriptionClick(); + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: subscription.name.toString().toText( + fontSize: 18, + color: textColor, ), - ).toCircle( - borderRadius: 122, - ), - 6.width, - "Subscribed".toText(color: Colors.white, isBold: true) - ], - ).toContainer( - backgroundColor: MyColors.primaryColor, - borderRadius: 20, - padding: const EdgeInsets.symmetric( - horizontal: 6, - vertical: 3, - ), - ) - ], - ), - 6.height, - showItem("Ads:", subscription.numberOfAds.toString()), - showItem("Users:", subscription.numberOfSubUsers.toString()), - showItem("Branches:", subscription.numberOfBranches.toString()), - 14.height, - Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Expanded( - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - subscription.price.toString().toText( - fontSize: 26, - isBold: true, - color: textColor, - ), - 2.width, - "${subscription.currency}/Month".toText( - color: MyColors.lightTextColor, - fontSize: 16, - ), - ], ), - ), - if (!isSubscribed) - Row( - children: [ - "Upgrade".toText( - fontSize: 14, - color: textColor, + if (isSubscribed) + Row( + children: [ + Container( + color: MyColors.white, + padding: const EdgeInsets.all(2), + child: const Icon( + Icons.done, + size: 8, + color: MyColors.primaryColor, + ), + ).toCircle( + borderRadius: 122, + ), + 6.width, + "Subscribed".toText(color: Colors.white, isBold: true) + ], + ).toContainer( + backgroundColor: MyColors.primaryColor, + borderRadius: 20, + padding: const EdgeInsets.symmetric( + horizontal: 6, + vertical: 3, ), - 4.width, - Icon( - Icons.arrow_forward, - size: 16, - color: textColor, - ) - ], - ) - ], - ), - if (isSubscribed) + ) + ], + ), + 6.height, + showItem("Ads:", subscription.numberOfAds.toString()), + showItem("Users:", subscription.numberOfSubUsers.toString()), + showItem("Branches:", subscription.numberOfBranches.toString()), + 14.height, Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, children: [ - "Expires on ${DateHelper.formatAsDayMonthYear(subscription.dateEnd)}".toText( - fontSize: 14, - color: textColor, - ), - 6.width, - "Renew".toText( - color: MyColors.primaryColor, - fontSize: 14, - textDecoration: TextDecoration.underline, - isBold: true, + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + subscription.price.toString().toText( + fontSize: 26, + isBold: true, + color: textColor, + ), + 2.width, + "${subscription.currency}/Month".toText( + color: MyColors.lightTextColor, + fontSize: 16, + ), + ], + ), ), + if (!isSubscribed) + Row( + children: [ + "Upgrade".toText( + fontSize: 14, + color: textColor, + ), + 4.width, + Icon( + Icons.arrow_forward, + size: 16, + color: textColor, + ) + ], + ) ], - ) - ], - ).toWhiteContainer( - width: double.infinity, - allPading: 12, - backgroundColor: backgroundColor, - margin: const EdgeInsets.symmetric( - horizontal: 21, + ), + if (isSubscribed) + Row( + children: [ + "Expires on ${DateHelper.formatAsDayMonthYear(subscription.dateEnd)}" + .toText( + fontSize: 14, + color: textColor, + ), + Row( + children: [ + 6.width, + "Renew".toText( + color: MyColors.primaryColor, + fontSize: 14, + textDecoration: TextDecoration.underline, + isBold: true, + ), + ], + ).onPress(() { + onRenewSubscriptionClick(); + }), + ], + ) + ], + ).toWhiteContainer( + width: double.infinity, + allPading: 12, + backgroundColor: backgroundColor, + margin: const EdgeInsets.symmetric( + horizontal: 21, + ), ), ); } diff --git a/pubspec.lock b/pubspec.lock index 339d8be..4caf0fa 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -129,6 +129,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" + device_info_plus: + dependency: transitive + description: + name: device_info_plus + sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110" + url: "https://pub.dev" + source: hosted + version: "9.1.2" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: d3b01d5868b50ae571cd1dc6e502fc94d956b665756180f7b16ead09e836fd64 + url: "https://pub.dev" + source: hosted + version: "7.0.0" dropdown_button2: dependency: transitive description: @@ -173,10 +189,10 @@ packages: dependency: transitive description: name: ffi - sha256: "13a6ccf6a459a125b3fcdb6ec73bd5ff90822e071207c663bfd1f70062d51d18" + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "2.1.0" file: dependency: transitive description: @@ -189,10 +205,10 @@ packages: dependency: transitive description: name: file_picker - sha256: "704259669b5e9cb24e15c11cfcf02caf5f20d30901b3916d60b6d1c2d647035f" + sha256: "4e42aacde3b993c5947467ab640882c56947d9d27342a5b6f2895b23956954a6" url: "https://pub.dev" source: hosted - version: "4.6.1" + version: "6.1.1" flutter: dependency: "direct main" description: flutter @@ -273,34 +289,34 @@ packages: dependency: transitive description: name: geocoding - sha256: e1dc0ac56666d9ed1d5a9ae5543ce9eb5986db6209cc7600103487d09192059c + sha256: "06d053a67733d1b9b4267259713913bc2aa750f18b830f0869ff337a8cfa8325" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.2.0" geocoding_android: dependency: transitive description: name: geocoding_android - sha256: "609db1d71bc364dd9d0616f72a41c01e0c74f3a3807efb85e0d5a67e57baf50f" + sha256: "287a2009cb2c3d3dd2899ba8f3d3e38d9e06905ea429283859bfc3586d4f57fd" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "3.2.0" geocoding_ios: dependency: transitive description: name: geocoding_ios - sha256: "8f79e380abb640ef4d88baee8bb65390058c802601158d0813dc990b36b189d2" + sha256: "8a39bfb650af55209c42e564036a550b32d029e0733af01dc66c5afea50388d3" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.3.0" geocoding_platform_interface: dependency: transitive description: name: geocoding_platform_interface - sha256: "8848605d307d844d89937cdb4b8ad7dfa880552078f310fa24d8a460f6dddab4" + sha256: "8c2c8226e5c276594c2e18bfe88b19110ed770aeb7c1ab50ede570be8b92229b" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.2.0" geolocator: dependency: transitive description: @@ -648,10 +664,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: a34ecd7fb548f8e57321fd8e50d865d266941b54e6c3b7758cf8f37c24116905 + sha256: "1cb68ba4cd3a795033de62ba1b7b4564dace301f952de6bfb3cd91b202b6ee96" url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "2.1.7" pedantic: dependency: transitive description: @@ -1069,10 +1085,18 @@ packages: dependency: transitive description: name: win32 - sha256: c0e3a4f7be7dae51d8f152230b86627e3397c1ba8c3fa58e63d44a9f3edc9cef + sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" + url: "https://pub.dev" + source: hosted + version: "5.2.0" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "41fd8a189940d8696b1b810efb9abcf60827b6cbfab90b0c43e8439e3a39d85a" url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "1.1.2" xdg_directories: dependency: transitive description: @@ -1090,5 +1114,5 @@ packages: source: hosted version: "6.1.0" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" + dart: ">=3.2.0 <4.0.0" flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index 055878a..036b00d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -34,6 +34,7 @@ dependencies: # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 + # mc_common_app: ## git: https://gitlab.com/mirza.shafique/car_common_app.git # path: C:/Users/mirza.shafique/AndroidStudioProjects/mc_common_app