Merge branch 'mirza_dev' of http://34.17.52.79/Haroon6138/car_provider_app into faiz_dev

# Conflicts:
#	lib/views/dashboard/fragments/ads_fragment.dart
#	pubspec.lock
aamir_dev
Faiz Hashmi 2 years ago
commit 0599bed068

@ -1,9 +1,9 @@
import 'package:car_provider_app/repositories/branch_repo.dart';
import 'package:car_provider_app/repositories/items_repo.dart';
import 'package:car_provider_app/repositories/schedule_repo.dart';
import 'package:car_provider_app/repositories/subscription_repo.dart';
import 'package:mc_common_app/config/dependencies.dart';
import 'package:mc_common_app/repositories/subscription_repo.dart';
class ProviderAppDependencies {
static void addDependencies() {

@ -29,9 +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';
@ -67,13 +70,19 @@ 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";
static final Map<String, WidgetBuilder> routes = {
//Home page
AppRoutes.dashboard: (context) => const DashboardPage(),
AppRoutes.adsDetailView: (context) => AdsDetailView(adDetails: ModalRoute.of(context)!.settings.arguments as AdDetailsModel),
AppRoutes.adsDetailView: (context) => AdsDetailView(
adDetails:
ModalRoute.of(context)!.settings.arguments as AdDetailsModel),
AppRoutes.createAdView: (context) => const CreateAdView(),
//setting
@ -100,13 +109,15 @@ class ProviderAppRoutes {
//Requests
AppRoutes.requestsDetailPage: (context) => RequestDetailPage(
requestDetailPageArguments: ModalRoute.of(context)!.settings.arguments as RequestDetailPageArguments,
requestDetailPageArguments: ModalRoute.of(context)!.settings.arguments
as RequestDetailPageArguments,
),
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) =>
@ -130,10 +141,19 @@ class ProviderAppRoutes {
addSchedule: (context) => AddSchedulesPage(),
//Branch Duplication
matchServices: (context) => MatchedServicesPage((ModalRoute.of(context)!.settings.arguments) == null ? null : (ModalRoute.of(context)!.settings.arguments as MatchServicesArguments)),
matchServices: (context) => MatchedServicesPage(
(ModalRoute.of(context)!.settings.arguments) == null
? null
: (ModalRoute.of(context)!.settings.arguments
as MatchServicesArguments)),
AppRoutes.chatView: (context) => ChatView(
chatViewArguments: ModalRoute.of(context)!.settings.arguments as ChatViewArguments,
chatViewArguments:
ModalRoute.of(context)!.settings.arguments as ChatViewArguments,
),
//ADS:
AppRoutes.selectAdTypeView: (context) => SelectAdTypeView(
isProvider: ModalRoute.of(context)!.settings.arguments as bool),
};
}

@ -2,13 +2,11 @@ import 'package:car_provider_app/config/provider_dependencies.dart';
import 'package:car_provider_app/repositories/branch_repo.dart';
import 'package:car_provider_app/repositories/items_repo.dart';
import 'package:car_provider_app/repositories/schedule_repo.dart';
import 'package:car_provider_app/repositories/subscription_repo.dart';
import 'package:car_provider_app/view_models/branch_view_model.dart';
import 'package:car_provider_app/view_models/dashboard_view_model.dart';
import 'package:car_provider_app/view_models/items_view_model.dart';
import 'package:car_provider_app/view_models/schedule_view_model.dart';
import 'package:car_provider_app/view_models/service_view_model.dart';
import 'package:car_provider_app/view_models/subscriptions_view_model.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
@ -20,17 +18,22 @@ 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/subscription_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/subscriptions_view_model.dart';
import 'package:mc_common_app/view_models/user_view_model.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
@ -73,7 +76,8 @@ Future<void> main() async {
),
),
ChangeNotifierProvider<SubscriptionsVM>(
create: (_) => SubscriptionsVM(subscriptionRepo: injector.get<SubscriptionRepo>()),
create: (_) =>
SubscriptionsVM(subscriptionRepo: injector.get<SubscriptionRepo>()),
),
ChangeNotifierProvider<ItemsVM>(
create: (_) => ItemsVM(
@ -114,6 +118,11 @@ Future<void> main() async {
requestRepo: injector.get<RequestRepo>(),
),
),
ChangeNotifierProvider<PaymentVM>(
create: (_) => PaymentVM(
paymentService: injector.get<PaymentService>(),
paymentRepo: injector.get<PaymentsRepo>()),
),
],
child: const MyApp(),
).setupLocale());
@ -135,12 +144,19 @@ class MyApp extends StatelessWidget {
injector.get<AppState>().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,

@ -1,27 +0,0 @@
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/subscriptions_models/subscription_model.dart';
import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart';
abstract class SubscriptionRepo {
Future<SubscriptionModel> getAllSubscriptions(String? serviceProviderID);
}
class SubscriptionRepoImp extends SubscriptionRepo {
@override
Future<SubscriptionModel> getAllSubscriptions(String? serviceProviderID) async {
String t = AppState().getUser.data!.accessToken ?? "";
Map<String, String> queryParameters = {};
if (serviceProviderID != null) {
queryParameters = {
"ID": serviceProviderID,
};
}
return await injector.get<ApiClient>().getJsonForObject((json) => SubscriptionModel.fromJson(json), ApiConsts.getAllSubscriptions, token: t, queryParameters: queryParameters);
}
}

@ -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<String?> selectFile() async {
File? file = await commonServices.pickFile(fileType: FileType.image);
Future<String?> selectFile(BuildContext context) async {
File? file = await commonServices.pickFile(context,fileType: FileType.image);
if (file != null) {
int sizeInBytes = file.lengthSync();

@ -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<void> selectFile(int index) async {
Future<void> 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<void> 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,9 +387,10 @@ class ServiceVM extends BaseVM {
Future<void> getAllCities(
BranchDetailModel? branchData, String countryCode) async {
setState(ViewState.busy);
citiesDropList.clear();
citiesDropList = [];
cities = null;
cityId = -1;
cityValue = null;
cities = await commonRepo.getAllCites(countryId.toString());
cities!.data?.forEach((element) {
if (branchData != null && branchData.id != null) {
@ -511,7 +517,7 @@ class ServiceVM extends BaseVM {
Future<void> fetchProviderServices(String branchID, String categoryId) async {
servicesDropList = [];
services=null;
services = null;
setState(ViewState.busy);
services = await branchRepo.fetchProviderServices(branchID, categoryId);

@ -1,74 +0,0 @@
import 'package:car_provider_app/repositories/subscription_repo.dart';
import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/view_models/base_view_model.dart';
import 'package:mc_common_app/widgets/dropdown/dropdow_field.dart';
class SubscriptionsVM extends BaseVM {
final SubscriptionRepo subscriptionRepo;
SubscriptionsVM({required this.subscriptionRepo});
//All Subscriptions
int selectedIndex = 0;
late DropValue selectedMothlyTab;
List<DropValue> monthlyTabs = [];
late SubscriptionModel allSubscriptions;
List<Subscription> tempSubscriptions = [];
//My Subscriptions
//All Subscriptions
getAllAvailableSubscriptions(String? serviceProviderID) async {
selectedIndex = 0;
setState(ViewState.busy);
allSubscriptions = await subscriptionRepo.getAllSubscriptions(serviceProviderID);
if (allSubscriptions.messageStatus == 1) {
monthlyTabs.clear();
var idSet = <int>{};
for (var d in allSubscriptions.data ?? []) {
if (idSet.add(d.durationDays ?? 0)) {
monthlyTabs.add(DropValue(d.durationDays, _convertDaysToMonths(d.durationDays ?? 0), ""));
}
}
monthlyTabs.sort((a, b) => a.value.compareTo(b.value));
selectedMothlyTab = monthlyTabs.first;
filterSubscriptions();
setState(ViewState.idle);
} else {
setState(ViewState.error);
}
}
String _convertDaysToMonths(int days) {
final int months = days ~/ 30;
final int remainingDays = days % 30;
String _result = months > 0 ? '$months Month${months > 1 ? 's' : ''}${remainingDays > 0 ? ' & ' : ''}' : '';
_result += remainingDays > 0 ? '$remainingDays Day${remainingDays > 1 ? 's' : ''}' : '';
return _result;
}
filterSubscriptions() {
tempSubscriptions.clear();
for (var element in allSubscriptions.data!) {
if (selectedMothlyTab.id == element.durationDays) {
tempSubscriptions.add(element);
}
}
}
//My Subscriptions
getMySubscriptions(String? serviceProviderID) async {
selectedIndex = 0;
setState(ViewState.busy);
allSubscriptions = await subscriptionRepo.getAllSubscriptions(serviceProviderID);
if (allSubscriptions.messageStatus == 1) {
// allSubscriptions.data!.sort((a, b) => a.value.compareTo(b.value));
setState(ViewState.idle);
} else {
setState(ViewState.error);
}
}
}

@ -80,7 +80,7 @@ class UpdateAppointmentPage extends StatelessWidget {
Column(
children: [
showPayNowButton(context, appointmentsVM),
21.height,
12.height,
showCancelButton(context, appointmentsVM),
],
).paddingAll(21),
@ -102,7 +102,7 @@ class UpdateAppointmentPage extends StatelessWidget {
Column(
children: [
showPayNowButton(context, appointmentsVM),
21.height,
12.height,
showPayLaterButton(context, appointmentsVM),
],
).paddingAll(21),
@ -113,7 +113,9 @@ class UpdateAppointmentPage extends StatelessWidget {
AppointmentStatusEnum.workStarted) &&
appointmentListModel.appointmentPaymentStatusEnum ==
AppointmentPaymentStatusEnum.payNow)
"Waiting for the payment from the customer".toText(),
"Waiting for the payment from the customer"
.toText()
.paddingAll(21),
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.arrived &&
@ -134,7 +136,7 @@ class UpdateAppointmentPage extends StatelessWidget {
Column(
children: [
showPayLaterButton(context, appointmentsVM),
21.height,
12.height,
showPayNowButton(context, appointmentsVM),
],
).paddingAll(21),
@ -154,7 +156,7 @@ class UpdateAppointmentPage extends StatelessWidget {
AppointmentStatusEnum.workStarted &&
appointmentListModel.appointmentPaymentStatusEnum ==
AppointmentPaymentStatusEnum.payLater)
showPayNowButton(context, appointmentsVM),
showPayNowButton(context, appointmentsVM).paddingAll(21),
if (appointmentListModel.appointmentStatusEnum ==
AppointmentStatusEnum.visitCompleted)
@ -234,6 +236,7 @@ class UpdateAppointmentPage extends StatelessWidget {
"appointmentID": appointmentListModel.id.toString(),
"appointmentServicePaymentStatusID": 2
});
_updateAppointment(context, appointmentListModel.branchId ?? 0);
Utils.hideLoading(context);
},
);
@ -249,6 +252,7 @@ class UpdateAppointmentPage extends StatelessWidget {
"appointmentID": appointmentListModel.id.toString(),
"appointmentStatusID": 3
});
_updateAppointment(context, appointmentListModel.branchId ?? 0);
Utils.hideLoading(context);
},
);
@ -265,6 +269,7 @@ class UpdateAppointmentPage extends StatelessWidget {
"appointmentID": appointmentListModel.id.toString(),
"appointmentServicePaymentStatusID": 4
});
_updateAppointment(context, appointmentListModel.branchId ?? 0);
Utils.hideLoading(context);
},
);
@ -281,6 +286,7 @@ class UpdateAppointmentPage extends StatelessWidget {
"appointmentID": appointmentListModel.id.toString(),
"appointmentStatusID": 8
});
_updateAppointment(context, appointmentListModel.branchId ?? 0);
Utils.hideLoading(context);
},
);

@ -43,10 +43,8 @@ class _DashboardPageState extends State<DashboardPage> {
void initState() {
super.initState();
dashboardVM = Provider.of<DashboardVM>(context, listen: false);
scheduleMicrotask(() {
context.read<RequestsVM>().populateRequestsFilterList();
_onRefresh();
});
context.read<RequestsVM>().populateRequestsFilterList();
_onRefresh();
}
Future<void> _onRefresh() async {
@ -57,32 +55,40 @@ class _DashboardPageState extends State<DashboardPage> {
context.read<ServiceVM>().getBranchAndServices();
AdVM adVm = Provider.of<AdVM>(context, listen: false);
AppointmentsVM appointmentsVM =
Provider.of<AppointmentsVM>(context, listen: false);
Provider.of<AppointmentsVM>(context, listen: false);
if (appointmentsVM.myAppointments.isEmpty) {
await appointmentsVM.getProviderMyAppointments({
"ServiceProviderID": injector
.get<AppState>()
.getUser
.data
?.userInfo
?.providerId
.toString() ??
.get<AppState>()
.getUser
.data
?.userInfo
?.providerId
.toString() ??
"0"
});
}
adVm.populateAdsFilterList();
if (adVm.myAds.isEmpty) {
await adVm.getMyAds();
}
if (adVm.exploreAds.isEmpty) {
await adVm.getExploreAds();
}
if (adVm.vehicleTypes.isEmpty) {
await adVm.getVehicleTypes();
}
if (adVm.vehicleAdsDurations.isEmpty) {
await adVm.getVehicleAdsDuration();
}
if (requestsVM.myRequests.isEmpty) {
await requestsVM.getRequests(appType: AppType.provider);
}
await chatVM.buildHubConnection(context);
// await chatVM.buildHubConnection(context);
}
@override
@ -92,11 +98,17 @@ class _DashboardPageState extends State<DashboardPage> {
onBackButtonTapped: () {
dashboardVM.updateIndex(2);
},
onRefresh: () async {
context.read<ServiceVM>().getBranchAndServices();
},
),
BranchAppointmentFragment(
onBackButtonTapped: () {
dashboardVM.updateIndex(2);
},
onRefresh: () async {
context.read<ServiceVM>().getBranchAndServices();
},
),
HomeFragment(
onTap: () {
@ -114,7 +126,11 @@ class _DashboardPageState extends State<DashboardPage> {
dashboardVM.updateIndex(2);
},
),
const MyRequestsFragment(),
MyRequestsFragment(
onBackButtonTapped: () {
dashboardVM.updateIndex(2);
},
),
];
return Scaffold(

@ -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),
),
);
}
},
),

@ -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<AppointmentsVM>().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<DashboardVM>().onNavbarTapped(3);
// context.read<AdVM>().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<DashboardVM>().onNavbarTapped(3);
// context.read<AdVM>().updateIsExploreAds(true);
// context.read<AdVM>().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<AppointmentsVM>().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<DashboardVM>().onNavbarTapped(3);
// context.read<AdVM>().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<DashboardVM>().onNavbarTapped(3);
// context.read<AdVM>().updateIsExploreAds(true);
// context.read<AdVM>().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,
// ),
],
),
),
),

@ -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),
),
))
],

@ -35,8 +35,14 @@ class _CustomDrawerState extends State<CustomDrawer> {
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<CustomDrawer> {
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<CustomDrawer> {
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<CustomDrawer> {
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<CustomDrawer> {
),
),
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<CustomDrawer> {
),
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'));

@ -12,13 +12,15 @@ class AppMap extends StatefulWidget {
late AppMapState _state;
final Function onMapCreated;
AppMap(this.initialCamera, {required this.onCameraMove, required this.onMapCreated});
AppMap(this.initialCamera,
{required this.onCameraMove, required this.onMapCreated});
@override
State<StatefulWidget> createState() => _state = AppMapState();
moveTo({required CameraPosition cameraPostion}) {
_state.googleMapController.animateCamera(CameraUpdate.newCameraPosition(cameraPostion));
_state.googleMapController
.animateCamera(CameraUpdate.newCameraPosition(cameraPostion));
}
}
@ -35,6 +37,12 @@ class AppMapState extends State<AppMap> {
@override
void initState() {}
@override
void dispose() {
super.dispose();
googleMapController.dispose();
}
@override
Widget build(BuildContext context) {
if (isHuawei == null) return CircularProgressIndicator();
@ -47,7 +55,9 @@ class AppMapState extends State<AppMap> {
zoomControlsEnabled: true,
myLocationButtonEnabled: true,
myLocationEnabled: true,
initialCameraPosition: CameraPosition.fromMap(widget.initialCamera) ?? const CameraPosition(target: LatLng(-26.1711459, 27.9002758), zoom: 2.0),
initialCameraPosition: CameraPosition.fromMap(widget.initialCamera) ??
const CameraPosition(
target: LatLng(-26.1711459, 27.9002758), zoom: 2.0),
onCameraMove: widget.onCameraMove,
onMapCreated: (GoogleMapController controller) {
googleMapController = controller;

@ -54,6 +54,11 @@ class _PickLocationPageState extends State<PickLocationPage> {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -117,10 +122,7 @@ class _PickLocationPageState extends State<PickLocationPage> {
Future<void> _updatePosition(CameraPosition _position) async {
latitude = _position.target.latitude;
longitude = _position.target.longitude;
// List<Placemark> placemarks = await placemarkFromCoordinates(latitude, longitude);
// _counter.value = '${placemarks.first.street}, ${placemarks.first.subLocality}, ${placemarks.first.locality}, ${placemarks.first.postalCode}, ${placemarks.first.country}';
print("Address121: " + _counter.value);
// _counter.value = (placemarks.first.name) ?? "" + " " + (placemarks.first.street ?? "") + " " + (placemarks.first.country ?? "");
updateAddress(latitude, longitude);
}
void _getUserLocation() async {
@ -130,21 +132,32 @@ class _PickLocationPageState extends State<PickLocationPage> {
latitude = position.latitude;
longitude = position.longitude;
setMap();
updateAddress(latitude, longitude);
} else {
requestPermissions().then(
(value) async {
if (value[Permission.location]!.isGranted) {
var position = await GeolocatorPlatform.instance.getCurrentPosition();
var position =
await GeolocatorPlatform.instance.getCurrentPosition();
currentPostion = LatLng(position.latitude, position.longitude);
latitude = position.latitude;
longitude = position.longitude;
setMap();
updateAddress(latitude, longitude);
}
},
);
}
}
updateAddress(double latitude, double longitude) async {
// List<Placemark> placemarks =
// await placemarkFromCoordinates(latitude, longitude);
// _counter.value =
// '${placemarks.first.street}, ${placemarks.first.subLocality}, ${placemarks.first.locality}, ${placemarks.first.postalCode}, ${placemarks.first.country}';
// print("Address121: " + placemarks[0].toString());
}
setMap() {
setState(() {
_kGooglePlex = CameraPosition(

@ -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(
@ -165,17 +178,22 @@ class BranchDetailPage extends StatelessWidget {
);
}),
categories.isEmpty
? LocaleKeys.no_branch.tr().toText(fontSize: 12)
? "No Service Added Yet".toText(fontSize: 12)
: ListView.separated(
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());
},
),
),

@ -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<ServiceVM>().selectedBranchStatus == 3 ? 0 : context.watch<ServiceVM>().selectedBranchStatus,
context.watch<ServiceVM>().selectedBranchStatus == 3
? 0
: context.watch<ServiceVM>().selectedBranchStatus,
[
DropValue(3, "Active", ""),
DropValue(1, "Requested", ""),
@ -74,95 +82,130 @@ class BranchListPage extends StatelessWidget {
} else {
List<BranchDetailModel> 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),
),
);
}
},
),

@ -111,8 +111,8 @@ class _DealerUserPageState extends State<DealerUserPage> {
("${model.branchUserList[index].firstName} ${model.branchUserList[index].lastName}").toText(fontSize: 16, isBold: true),
8.height,
itemWidget("Role", "Dealer User"),
itemWidget("Email", model.branchUserList[index].email),
itemWidget("Phone", model.branchUserList[index].mobileNo)
itemWidget("Email", model.branchUserList[index].email??""),
itemWidget("Phone", model.branchUserList[index].mobileNo??"")
],
),
),

@ -90,7 +90,7 @@ class _AssignDealerUserSheetState extends State<AssignDealerUserSheet> {
Utils.showLoading(context);
List<int> userIds = [];
for (var element in provider.allProviderDealersList) {
if (element.isBranchUser) {
if (element.isBranchUser??false) {
userIds.add(element.id);
}
}
@ -156,8 +156,8 @@ class _AssignDealerUserSheetState extends State<AssignDealerUserSheet> {
("${model.allProviderDealersList[index].firstName} ${model.allProviderDealersList[index].lastName}").toText(fontSize: 16, isBold: true),
8.height,
itemWidget("Role", "Dealer User"),
itemWidget("Email", model.allProviderDealersList[index].email),
itemWidget("Phone", model.allProviderDealersList[index].mobileNo)
itemWidget("Email", model.allProviderDealersList[index].email??""),
itemWidget("Phone", model.allProviderDealersList[index].mobileNo??"")
],
),
),
@ -181,7 +181,7 @@ class _AssignDealerUserSheetState extends State<AssignDealerUserSheet> {
bool validation() {
bool isValid = false;
for (var element in provider.allProviderDealersList) {
if (element.isBranchUser) {
if (element.isBranchUser??false) {
isValid = true;
}
}

@ -28,7 +28,8 @@ class DefineBranchPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
ServiceVM branchVM = context.read<ServiceVM>();
branchVM.getAllCountriesList(branchData, EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
branchVM.getAllCountriesList(branchData,
EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
return Scaffold(
appBar: CustomAppBar(
title: LocaleKeys.defineBranches.tr(),
@ -50,10 +51,18 @@ class DefineBranchPage extends StatelessWidget {
model.country != null
? DropdownField(
(DropValue value) {
model.countryValue =
DropValue(value.id, value.value, "");
model.countryCode = value.subValue;
model.countryId = value.id;
model.getAllCities(branchData, EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
model.getAllCities(
branchData,
EasyLocalization.of(context)
?.currentLocale
?.countryCode ??
"SA");
},
isSelectAble: branchData == null ? true : false,
list: model.countryDropList,
dropdownValue: model.countryValue,
hint: "${LocaleKeys.chooseCountry.tr()}*",
@ -66,7 +75,8 @@ class DefineBranchPage extends StatelessWidget {
? Text(LocaleKeys.no_city_available.tr())
: DropdownField(
(DropValue value) {
// countryCode = value.subValue;
model.cityValue = DropValue(
value.id, value.value, "");
model.setOnlyState(ViewState.busy);
model.cityId = value.id;
model.setState(ViewState.idle);
@ -111,7 +121,9 @@ class DefineBranchPage extends StatelessWidget {
navigateTo(
context,
PickLocationPage(
onPickAddress: (double latitude, double longitude, String address) {
onPickAddress: (double latitude,
double longitude, String address) {
print("tesssgngl " + address);
model.latitude = latitude;
model.longitude = longitude;
model.address = address;
@ -125,12 +137,16 @@ class DefineBranchPage extends StatelessWidget {
height: 45,
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.all(color: MyColors.darkPrimaryColor, width: 2),
borderRadius: const BorderRadius.all(Radius.circular(8)),
border: Border.all(
color: MyColors.darkPrimaryColor,
width: 2),
borderRadius: const BorderRadius.all(
Radius.circular(8)),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
const Icon(
Icons.place_outlined,
@ -163,14 +179,24 @@ class DefineBranchPage extends StatelessWidget {
SizedBox(
width: double.infinity,
child: Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 20),
padding:
const EdgeInsets.only(left: 20, right: 20, bottom: 20),
child: ShowFillButton(
title: branchData != null ? (branchData!.id == null ? LocaleKeys.createBranch.tr() : LocaleKeys.updateBranch.tr()) : LocaleKeys.createBranch.tr(),
title: branchData != null
? (branchData!.id == null
? LocaleKeys.createBranch.tr()
: LocaleKeys.updateBranch.tr())
: LocaleKeys.createBranch.tr(),
onPressed: () async {
if (branchData == null) {
Utils.showLoading(context);
MResponse res =
await model.createBranch(model.branchName, model.branchDescription, model.cityId.toString(), model.address, model.latitude.toString(), model.longitude.toString());
MResponse res = await model.createBranch(
model.branchName,
model.branchDescription,
model.cityId.toString(),
model.address,
model.latitude.toString(),
model.longitude.toString());
Utils.hideLoading(context);
if (res.messageStatus == 1) {
Utils.showToast(LocaleKeys.branch_created.tr());
@ -182,7 +208,13 @@ class DefineBranchPage extends StatelessWidget {
} else {
Utils.showLoading(context);
MResponse res = await model.updateBranch(
branchData!.id ?? 0, model.branchName, model.branchDescription, model.cityId.toString(), model.address, model.latitude.toString(), model.longitude.toString());
branchData!.id ?? 0,
model.branchName,
model.branchDescription,
model.cityId.toString(),
model.address,
model.latitude.toString(),
model.longitude.toString());
Utils.hideLoading(context);
if (res.messageStatus == 1) {
Utils.showToast(LocaleKeys.branch_updated.tr());

@ -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';
@ -130,7 +131,7 @@ class _DefineLicensePageState extends State<DefineLicensePage> {
maxLines: 3,
isBackgroundEnabled: true,
),
if (((model.document?.data![index].documentUrl ?? "").toString().isNotEmpty))
if ((model.document?.data![index].documentUrl ?? "").toString().isNotEmpty)
Column(
children: [
8.height,
@ -144,7 +145,9 @@ class _DefineLicensePageState extends State<DefineLicensePage> {
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,

@ -1,4 +1,3 @@
import 'package:car_provider_app/view_models/schedule_view_model.dart';
import 'package:car_provider_app/views/settings/schedule/widgets/chips_picker_item.dart';
import 'package:car_provider_app/views/settings/schedule/widgets/select_days_sheet.dart';
@ -10,6 +9,7 @@ import 'package:mc_common_app/models/appointments_models/schedule_model.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/date_helper.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';
@ -19,15 +19,24 @@ import 'package:mc_common_app/widgets/bottom_sheet.dart';
class AddSchedulesPage extends StatelessWidget {
late ScheduleVM mModel;
String name = "", startDate = "", endDate = "", startTime = "", endTime = "", slotsTime = "", appointmentPerSlot = "", servicesGroupID = "";
String name = "",
startDate = "",
endDate = "",
startTime = "",
endTime = "",
slotsTime = "",
appointmentPerSlot = "",
servicesGroupID = "";
late ScheduleData scheduleData;
AddSchedulesPage({Key? key}) : super(key: key);
setEditData() {
name = scheduleData.scheduleName ?? "";
startDate = DateHelper.formatAsYearMonthDay(scheduleData.fromDate ?? DateTime.now());
endDate = DateHelper.formatAsYearMonthDay(scheduleData.toDate ?? DateTime.now());
startDate = DateHelper.formatAsYearMonthDay(
scheduleData.fromDate ?? DateTime.now());
endDate =
DateHelper.formatAsYearMonthDay(scheduleData.toDate ?? DateTime.now());
startTime = scheduleData.startTime ?? "";
endTime = scheduleData.endTime ?? "";
slotsTime = scheduleData.slotDurationMinute.toString();
@ -35,7 +44,9 @@ class AddSchedulesPage extends StatelessWidget {
// mModel.selectedServicesItems.clear();
scheduleData.scheduleServices?.forEach((element) {
mModel.selectedServicesItems.add(PickerItem(id: element.providerServiceId ?? 0, title: element.providerServiceName ?? ""));
mModel.selectedServicesItems.add(PickerItem(
id: element.providerServiceId ?? 0,
title: element.serviceDescription ?? ""));
});
mModel.selectedDaysItems.clear();
scheduleData.weeklyOffDays?.forEach((element) {
@ -134,7 +145,7 @@ class AddSchedulesPage extends StatelessWidget {
),
8.height,
ChipsPickerItem(
hint: 'Days',
hint: 'Off Days',
itemsList: [...model.selectedDaysItems],
onClick: () {
showMyBottomSheet(
@ -179,7 +190,12 @@ class AddSchedulesPage extends StatelessWidget {
isNeedClickAll: true,
onTap: () async {
TimeOfDay _startTime = TimeOfDay.now();
if (startTime.isNotEmpty) _startTime = TimeOfDay(hour: int.parse(startTime.split(":")[0]), minute: int.parse(startTime.split(":")[1]));
if (startTime.isNotEmpty)
_startTime = TimeOfDay(
hour:
int.parse(startTime.split(":")[0]),
minute:
int.parse(startTime.split(":")[1]));
endTime = await Utils.pickTime(
context,
initialTime: _startTime,
@ -315,12 +331,16 @@ class AddSchedulesPage extends StatelessWidget {
Utils.hideLoading(context);
if (servicesResponse.messageStatus == 1) {
Utils.showToast("Successfully schedule created");
context.read<ScheduleVM>().getSchedules(scheduleData.branchId ?? "");
pop(context);
} else {
Utils.showToast("Something went wrong while adding services in schedule");
Utils.showToast(servicesResponse.message ?? "");
context.read<ScheduleVM>().getSchedules(scheduleData.branchId ?? "");
pop(context);
}
} else {
Utils.hideLoading(context);
Utils.showToast("Something went wrong");
Utils.showToast(scheduleResponse.message??"");
}
}
@ -362,8 +382,11 @@ class AddSchedulesPage extends StatelessWidget {
Utils.hideLoading(context);
if (servicesResponse.messageStatus == 1) {
Utils.showToast("Successfully schedule updated");
context.read<ScheduleVM>().getSchedules(scheduleData.branchId ?? "");
pop(context);
} else {
Utils.showToast("Something went wrong while adding services in schedule");
Utils.showToast(
"Something went wrong while adding services in schedule");
}
} else {
Utils.hideLoading(context);

@ -58,7 +58,10 @@ class _SchedulesListPageState extends State<SchedulesListPage> {
Row(
children: [
Expanded(
child: value.schedule!.data![index].scheduleName.toString().toText(
child: value.schedule!.data![index]
.scheduleName
.toString()
.toText(
fontSize: 16,
isBold: true,
),
@ -71,33 +74,81 @@ class _SchedulesListPageState extends State<SchedulesListPage> {
height: 16,
),
).onPress(() {
value.schedule!.data![index].branchId = widget.branchId ?? "";
navigateWithName(context, ProviderAppRoutes.addSchedule, arguments: value.schedule!.data![index]);
value.schedule!.data![index]
.branchId = widget.branchId ?? "";
navigateWithName(context,
ProviderAppRoutes.addSchedule,
arguments:
value.schedule!.data![index]);
}),
],
crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
),
12.height,
showItem("Start Date:", DateHelper.formatAsDayMonthYear(value.schedule!.data![index].fromDate)),
showItem("End Date:", DateHelper.formatAsDayMonthYear(value.schedule!.data![index].toDate)),
showItem("Off Days:", DateHelper.formatAsDayMonthYear(value.schedule!.data![index].fromDate)),
showItem("Shift Start Time:", value.schedule!.data![index].startTime ?? ""),
showItem("Shift End Time:", value.schedule!.data![index].startTime ?? ""),
showItem("Slots Time:", value.schedule!.data![index].slotDurationMinute.toString() + " Mins"),
showItem("Appointments Per Slot:", value.schedule!.data![index].perSlotAppointment.toString()),
showItem("Off Days", offDays(value.schedule!.data![index])),
showItem(
"Start Date:",
DateHelper.formatAsDayMonthYear(value
.schedule!.data![index].fromDate)),
showItem(
"End Date:",
DateHelper.formatAsDayMonthYear(value
.schedule!.data![index].toDate)),
showItem(
"Off Days:",
DateHelper.formatAsDayMonthYear(value
.schedule!.data![index].fromDate)),
showItem(
"Shift Start Time:",
value.schedule!.data![index]
.startTime ??
""),
showItem(
"Shift End Time:",
value.schedule!.data![index]
.startTime ??
""),
showItem(
"Slots Time:",
value.schedule!.data![index]
.slotDurationMinute
.toString() +
" Mins"),
showItem(
"Appointments Per Slot:",
value.schedule!.data![index]
.perSlotAppointment
.toString()),
showItem("Off Days",
offDays(value.schedule!.data![index])),
12.height,
"Services:".toText(fontSize: 12, isBold: true, color: MyColors.lightTextColor),
"Services:".toText(
fontSize: 12,
isBold: true,
color: MyColors.lightTextColor),
Column(
children: value.schedule!.data![index].scheduleServices!
.map((element) => Container(child: element.providerServiceName.toString().toText(fontSize: 12, isBold: true)))
crossAxisAlignment:
CrossAxisAlignment.start,
children: value.schedule!.data![index]
.scheduleServices!
.map(
(element) => Container(
child: element.serviceDescription
.toString()
.toText(
fontSize: 12,
isBold: true,
),
),
)
.toList(),
crossAxisAlignment: CrossAxisAlignment.start,
)
],
).toWhiteContainer(width: double.infinity, allPading: 12);
).toWhiteContainer(
width: double.infinity, allPading: 12);
},
separatorBuilder: (BuildContext context, int index) {
separatorBuilder:
(BuildContext context, int index) {
return 12.height;
},
padding: const EdgeInsets.all(20),
@ -111,7 +162,8 @@ class _SchedulesListPageState extends State<SchedulesListPage> {
maxWidth: double.infinity,
margin: const EdgeInsets.all(20),
onPressed: () {
navigateWithName(context, ProviderAppRoutes.addSchedule, arguments: ScheduleData(branchId: widget.branchId ?? ""));
navigateWithName(context, ProviderAppRoutes.addSchedule,
arguments: ScheduleData(branchId: widget.branchId ?? ""));
},
),
],
@ -123,7 +175,8 @@ class _SchedulesListPageState extends State<SchedulesListPage> {
String offDays(ScheduleData scheduleData) {
String offDays = "";
for (int i = 0; i < scheduleData.weeklyOffDays!.length; i++) {
offDays = offDays + initDaysList[scheduleData.weeklyOffDays![i].dayNumber! - 1].title;
offDays = offDays +
initDaysList[scheduleData.weeklyOffDays![i].dayNumber! - 1].title;
if (i != scheduleData.weeklyOffDays!.length - 1) {
offDays = offDays + " , ";
}
@ -134,7 +187,8 @@ class _SchedulesListPageState extends State<SchedulesListPage> {
Widget showItem(String title, String value) {
return Row(
children: [
title.toText(fontSize: 12, isBold: true, color: MyColors.lightTextColor),
title.toText(
fontSize: 12, isBold: true, color: MyColors.lightTextColor),
4.width,
value.toText(fontSize: 12, isBold: true),
],

@ -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<CreateItemPage> {
onTap: () async {
bool isPermissionsAvailable = await requestPermissionGranted(context, Permission.storage);
if (isPermissionsAvailable && model != null) {
itemImage = await model!.selectFile() ?? "";
itemImage = await model!.selectFile(context) ?? "";
setState(() {});
}
},

@ -1,4 +1,3 @@
import 'package:car_provider_app/generated/locale_keys.g.dart';
import 'package:car_provider_app/view_models/service_view_model.dart';
import 'package:car_provider_app/views/settings/services/services_list_page.dart';
@ -29,20 +28,26 @@ class CreateServicesPage3 extends StatelessWidget {
String chargersPerKm = "0";
int? categoryId;
int? serviceId = -1;
DropValue? category;
DropValue? service;
@override
Widget build(BuildContext context) {
ServiceVM serviceVM = context.read<ServiceVM>();
if (branchModel!.categoryId == null) {
serviceVM.fetchBranchCategory(EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
serviceVM.fetchBranchCategory(
EasyLocalization.of(context)?.currentLocale?.countryCode ?? "SA");
} else {
isAppointmentAvailable = branchModel?.serviceProviderService?.isAllowAppointment ?? false;
isAppointmentAvailable =
branchModel?.serviceProviderService?.isAllowAppointment ?? false;
// isHomeAppointmentAvailable=branchModel.serviceProviderService.
serviceRage = branchModel?.serviceProviderService?.customerLocationRange ?? 0;
serviceRage =
branchModel?.serviceProviderService?.customerLocationRange ?? 0;
if (serviceRage > 0) {
isHomeAppointmentAvailable = true;
}
chargersPerKm = branchModel?.serviceProviderService?.rangePricePerKm ?? "0";
chargersPerKm =
branchModel?.serviceProviderService?.rangePricePerKm ?? "0";
serviceId = branchModel?.serviceProviderService?.serviceId ?? -1;
}
return Scaffold(
@ -67,7 +72,8 @@ class CreateServicesPage3 extends StatelessWidget {
fontWeight: FontWeight.bold,
),
).toContainer(
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 12, top: 12),
padding: const EdgeInsets.only(
left: 8, right: 8, bottom: 12, top: 12),
backgroundColor: MyColors.textFieldColor,
borderRadius: 0,
width: double.infinity,
@ -81,34 +87,44 @@ class CreateServicesPage3 extends StatelessWidget {
fontWeight: FontWeight.bold,
),
).toContainer(
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 12, top: 12),
padding: const EdgeInsets.only(
left: 8, right: 8, bottom: 12, top: 12),
backgroundColor: MyColors.textFieldColor,
borderRadius: 0,
width: double.infinity,
)
: (branchModel!.categoryId == null && model.categoryDropList.isNotEmpty)
: (branchModel!.categoryId == null &&
model.categoryDropList.isNotEmpty)
? DropdownField(
(DropValue value) async {
categoryId = value.id;
category = value;
service = null;
serviceId = -1;
isAppointmentAvailable = false;
isHomeAppointmentAvailable = false;
model.fetchServicesByCategoryId(value.id.toString());
model.fetchServicesByCategoryId(
value.id.toString());
},
dropdownValue: category,
list: model.categoryDropList,
hint: LocaleKeys.selectServiceCategory.tr(),
hint:
LocaleKeys.selectServiceCategory.tr(),
)
: const CircularProgressIndicator(),
12.height,
branchModel!.serviceProviderService != null
? Text(
branchModel!.serviceProviderService!.serviceDescription ?? "N/A",
branchModel!.serviceProviderService!
.serviceDescription ??
"N/A",
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
),
).toContainer(
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 12, top: 12),
padding: const EdgeInsets.only(
left: 8, right: 8, bottom: 12, top: 12),
backgroundColor: MyColors.textFieldColor,
borderRadius: 0,
width: double.infinity,
@ -117,10 +133,12 @@ class CreateServicesPage3 extends StatelessWidget {
? DropdownField(
(DropValue value) {
serviceId = value.id;
service = value;
isAppointmentAvailable = false;
isHomeAppointmentAvailable = false;
model.setState(ViewState.idle);
},
dropdownValue: service,
list: model.servicesDropList,
hint: LocaleKeys.defineServices.tr(),
)
@ -135,7 +153,8 @@ class CreateServicesPage3 extends StatelessWidget {
CheckBoxWithTitleDescription(
isSelected: isAppointmentAvailable,
title: 'Available for appointment',
description: 'This option will allow customer to book appointment for these services',
description:
'This option will allow customer to book appointment for these services',
onSelection: (bool v) {
isAppointmentAvailable = v;
model.setState(ViewState.idle);
@ -145,7 +164,8 @@ class CreateServicesPage3 extends StatelessWidget {
CheckBoxWithTitleDescription(
isSelected: isHomeAppointmentAvailable,
title: 'Allow home services',
description: 'This option will allow customer to book appointment at their desired location',
description:
'This option will allow customer to book appointment at their desired location',
onSelection: (bool v) {
isHomeAppointmentAvailable = v;
model.setState(ViewState.idle);
@ -158,13 +178,18 @@ class CreateServicesPage3 extends StatelessWidget {
TxtField(
hint: "Home Services Range",
keyboardType: TextInputType.number,
value: serviceRage == 0 ? null : serviceRage.toString(),
value: serviceRage == 0
? null
: serviceRage.toString(),
postfixWidget: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
children: [
"KM".toText(color: MyColors.lightTextColor),
"KM".toText(
color: MyColors.lightTextColor),
],
),
onChanged: (v) {
@ -179,7 +204,9 @@ class CreateServicesPage3 extends StatelessWidget {
TxtField(
hint: "Charges per Kilometer",
keyboardType: TextInputType.number,
value: chargersPerKm == "0.0" ? null : chargersPerKm,
value: chargersPerKm == "0.0"
? null
: chargersPerKm,
onChanged: (v) {
if (v.isNotEmpty) {
chargersPerKm = v;

@ -1,11 +1,19 @@
import 'package:car_provider_app/view_models/subscriptions_view_model.dart';
import 'package:car_provider_app/config/provider_routes.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/view_models/subscriptions_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<SubscriptionsVM>().getMySubscriptions(AppState().getUser.data?.userInfo?.providerId.toString() ?? "");
context.read<SubscriptionsVM>().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<SubscriptionsVM>(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<SubscriptionsVM>(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<PaymentVM>()
.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,
],
),
),
);
}

@ -0,0 +1,122 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
class DegradePackageSheet extends StatelessWidget {
const DegradePackageSheet({super.key});
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
"Deactivate the branches & users".toText(
fontSize: 18,
isBold: true,
),
"To select this subscription you need to deactivate your branches and users as this package only supports 1 branch and 2 users per branch. You can reactivate these branches later after upgrading the package"
.toText(
fontSize: 14,
color: MyColors.lightTextColor,
),
12.height,
showBranchList(),
12.height,
],
),
);
}
Widget showBranchList() {
return ListView.separated(
itemBuilder: (context, index) {
return Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
customCheckBox(true),
12.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
"Olaya Branch".toText(
fontSize: 16,
isBold: true,
),
"3 Users".toText(
fontSize: 10,
color: MyColors.lightTextColor,
),
],
),
),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.keyboard_arrow_down,
),
)
],
),
showUser("Mirza"),
12.height,
showUser("Shafique"),
],
).toContainer(
isShadowEnabled: true,
borderRadius: 0,
paddingAll: 12,
);
},
separatorBuilder: (context, index) {
return 12.height;
},
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: 2,
);
}
Widget showUser(String user) {
return Row(
children: [
const SizedBox(
width: 24,
),
customCheckBox(false),
12.width,
user.toText(fontSize: 14),
],
);
}
Widget customCheckBox(bool isChecked) {
return SizedBox(
height: 18,
width: 18,
child: isChecked
? const Icon(
Icons.done,
color: Colors.white,
size: 14,
)
: const SizedBox(),
).toContainer(
isEnabledBorder: true,
paddingAll: 0,
borderRadius: 0,
borderWidget: 1,
borderColor: MyColors.primaryColor,
backgroundColor: isChecked ? MyColors.primaryColor : Colors.transparent,
);
}
}

@ -0,0 +1,294 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/general_models/m_response.dart';
import 'package:mc_common_app/models/subscriptions_models/branch_user_selection_model.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/utils/utils.dart';
import 'package:mc_common_app/view_models/payment_view_model.dart';
import 'package:mc_common_app/view_models/subscriptions_view_model.dart';
import 'package:mc_common_app/views/payments/payment_methods_view.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
class DowngradeDataSheet extends StatefulWidget {
Subscription subscription;
DowngradeDataSheet(this.subscription, {super.key});
@override
State<DowngradeDataSheet> createState() => _DowngradeDataSheetState();
}
class _DowngradeDataSheetState extends State<DowngradeDataSheet> {
@override
void initState() {
super.initState();
context.read<SubscriptionsVM>().getSPBranchUser_Get();
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height / 1.2,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(12),
child: Column(
children: [
"Deactivate the branches & users".toText(
fontSize: 19,
isBold: true,
),
8.height,
"To select this subscription you need to deactivate your branches and users as this package only supports 1 branch and 2 users per branch. You can reactivate these branches later after upgrading the package"
.toText(
fontSize: 14,
color: MyColors.textColor,
),
],
),
),
Expanded(
child: Consumer<SubscriptionsVM>(
builder: (BuildContext context, model, Widget? child) {
return Column(
children: [
Expanded(
child: model.branchSelectionList == null
? const Center(child: CircularProgressIndicator())
: ListView.separated(
itemBuilder: (context, index) {
return showBranchItem(
model, model.branchSelectionList![index]);
},
separatorBuilder: (context, index) {
return 12.height;
},
padding: const EdgeInsets.all(12),
itemCount: model.branchSelectionList?.length ?? 0,
),
),
ShowFillButton(
title: "Next",
maxWidth: double.infinity,
margin: const EdgeInsets.all(12),
onPressed: () async {
List<int> listOfBranches = [];
List<int> listOfUsers = [];
for (var element in model.branchSelectionList!) {
if (element.isSelected) {
listOfBranches.add(element.branchId);
} else {
for (var element in element.usersList) {
if (element.isSelected) {
listOfUsers.add(element.userId);
}
}
}
}
print("opoewww");
print(jsonEncode(listOfBranches));
if (listOfBranches.isNotEmpty ||
listOfUsers.isNotEmpty) {
navigateTo(
context,
PaymentMethodsView(
paymentType: PaymentTypes.subscription,
onTempContinue: () async {
Utils.showLoading(context);
MResponse response =
await model.payForSubscription(
widget.subscription.id!,
true,
false,
widget.subscription.price.toString(),
isDegrade: true,
listOfBranches: listOfBranches,
listOfUsers: listOfUsers,
);
Utils.hideLoading(context);
if (response.messageStatus == 1) {
if(response.message!.contains("Your current sub-users are not")){
Utils.showToast(response.message.toString());
context.read<SubscriptionsVM>().getMySubscriptions(
AppState()
.getUser
.data
?.userInfo
?.providerId
.toString() ??
"");
pop(context);
return false;
}else{
context
.read<PaymentVM>()
.updateOrderProviderSubscriptionId(
id: response.data);
// Utils.showToast(
// "Subscriptions is successfully updated");
return true;
}
} else {
Utils.showToast(response.message.toString());
context.read<SubscriptionsVM>().getMySubscriptions(
AppState()
.getUser
.data
?.userInfo
?.providerId
.toString() ??
"");
return false;
}
},
),
);
}
},
),
],
);
},
),
),
],
),
);
}
Widget showBranchItem(SubscriptionsVM viewModel, BranchSelectionModel model) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
customCheckBox(model.isSelected).onPress(() {
model.isSelected = !model.isSelected;
if (model.isSelected) {
for (var element in model.usersList) {
element.isSelected = true;
}
} else {
for (var element in model.usersList) {
element.isSelected = false;
}
}
model.isOpend = true;
viewModel.setState(ViewState.idle);
}),
12.width,
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: double.infinity,
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
model.branchName.toText(
fontSize: 18,
isBold: true,
),
("${model.usersList.length} Users").toText(
fontSize: 10,
color: MyColors.lightTextColor,
)
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
model.isOpend
? Icons.keyboard_arrow_up_rounded
: Icons.keyboard_arrow_down_rounded,
),
],
),
],
),
),
if (model.isOpend) 12.height,
if (model.isOpend)
ListView.separated(
itemBuilder: (context, index) {
return Row(
children: [
customCheckBox(model.usersList[index].isSelected),
8.width,
model.usersList[index].userName.toText(
fontSize: 14,
),
],
).onPress(() {
// for (int i = 0; i < model.usersList.length; i++) {
// if (i != index) {
// model.usersList[index].isSelected = false;
// }
// }
model.usersList[index].isSelected =
!model.usersList[index].isSelected;
viewModel.setState(ViewState.idle);
});
},
separatorBuilder: (context, index) {
return 12.height;
},
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: model.usersList.length,
),
],
).onPress(() {
model.isOpend = !model.isOpend;
viewModel.setState(ViewState.idle);
}),
)
],
).toWhiteContainer(
width: double.infinity,
pading: const EdgeInsets.all(12),
);
}
Widget customCheckBox(bool isChecked) {
return SizedBox(
height: 18,
width: 18,
child: isChecked
? const Icon(
Icons.done,
color: Colors.white,
size: 14,
)
: const SizedBox(),
).toContainer(
isEnabledBorder: true,
paddingAll: 0,
borderRadius: 0,
borderWidget: 1,
borderColor: MyColors.primaryColor,
backgroundColor: isChecked ? MyColors.primaryColor : Colors.transparent,
);
}
}

@ -0,0 +1,89 @@
import 'package:car_provider_app/views/subscriptions/sheet/degrage_package_sheet.dart';
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/theme/colors.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/extensions/extensions_widget.dart';
class SelectPackageSheet extends StatelessWidget {
const SelectPackageSheet({super.key});
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
"When do you want to upgrade".toText(
fontSize: 19,
isBold: true,
),
12.height,
showPackage(),
12.height,
showPackage(),
12.height,
ShowFillButton(
title: "Upgrade",
maxWidth: double.infinity,
onPressed: () {
showMyBottomSheet(context, child: const DegradePackageSheet());
},
),
12.height,
],
),
);
}
Widget showPackage() {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Checkbox(
value: false,
onChanged: (v) {},
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
"Now".toText(
fontSize: 16,
isBold: true,
),
"Your subscription will upgrade now. Affecting from 23 January, 2024"
.toText(
fontSize: 12,
color: MyColors.lightTextColor,
),
12.height,
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
"175".toText(
fontSize: 26,
isBold: true,
),
2.width,
"SAR".toText(
color: MyColors.lightTextColor,
fontSize: 16,
),
],
)
],
),
)
],
).toContainer(isShadowEnabled: true);
}
}

@ -0,0 +1,199 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/general_models/m_response.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/date_helper.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/utils/utils.dart';
import 'package:mc_common_app/view_models/payment_view_model.dart';
import 'package:mc_common_app/view_models/subscriptions_view_model.dart';
import 'package:mc_common_app/views/payments/payment_methods_view.dart';
import 'package:mc_common_app/widgets/button/show_fill_button.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart';
class UpgradePackageSheet extends StatefulWidget {
Subscription subscription;
UpgradePackageSheet(this.subscription, {super.key});
@override
State<UpgradePackageSheet> createState() => _UpgradePackageSheetState();
}
class _UpgradePackageSheetState extends State<UpgradePackageSheet> {
bool isNowSelected = true;
String price = "0";
@override
void initState() {
// TODO: implement initState
super.initState();
calculateUpgradePrice();
}
calculateUpgradePrice() {
context.read<SubscriptionsVM>().calculationUpgradePrice(
AppState().getUser.data?.userInfo?.providerId.toString() ?? "",
widget.subscription.id.toString(),
);
}
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
padding: const EdgeInsets.only(left: 21, right: 21, bottom: 21, top: 4),
child: Consumer<SubscriptionsVM>(builder: (context, model, _) {
if (model.state == ViewState.busy) {
return SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height / 2,
child: const Center(child: CircularProgressIndicator()),
);
} else {
if (isNowSelected) {
price = model.newPrice.toString();
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
"When do you want to upgrade".toText(
fontSize: 18,
fontWeight: FontWeight.bold,
),
12.height,
packageItem(
"Now",
("Your subscription will upgrade now. Affecting from ${DateHelper.formatAsLongDate(widget.subscription.dateEnd!)}"),
model.newPrice.toString(),
isNowSelected,
).onPress(() {
setState(() {
price = model.newPrice.toString();
isNowSelected = true;
});
}),
6.height,
packageItem(
"Upgrade after current expiry",
("Your subscription will upgrade after you current subscription will end. Affecting from 27 January, 2024 ${DateHelper.formatAsLongDate(widget.subscription.dateEnd!)}"),
widget.subscription.price.toString(),
isNowSelected ? false : true,
).onPress(() {
price = widget.subscription.price.toString();
setState(() {
isNowSelected = false;
});
}),
12.height,
ShowFillButton(
title: "Upgrade",
maxWidth: double.infinity,
onPressed: () async {
navigateTo(
context,
PaymentMethodsView(
paymentType: PaymentTypes.subscription,
onTempContinue: () async {
Utils.showLoading(context);
MResponse mResponse = await model.payForSubscription(
widget.subscription.id!,
isNowSelected,
false,
price);
Utils.hideLoading(context);
if (mResponse.messageStatus == 1) {
context
.read<PaymentVM>()
.updateOrderProviderSubscriptionId(
id: mResponse.data);
// Utils.showToast(
// "Subscriptions is successfully updated");
return true;
} else {
Utils.showToast(mResponse.message.toString());
return false;
}
},
),
);
},
),
],
);
}
}),
);
}
Widget packageItem(
String title, String description, String price, bool isSelected) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Icon(
Icons.done,
size: 14,
color: Colors.white,
).toContainer(
isEnabledBorder: true,
backgroundColor:
isSelected ? MyColors.primaryColor : Colors.transparent,
borderColor: MyColors.primaryColor,
borderWidget: 1,
borderRadius: 0,
paddingAll: 2,
),
12.width,
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
title.toText(
fontSize: 16,
fontWeight: FontWeight.bold,
),
4.height,
if (widget.subscription.dateEnd != null)
description.toText(
fontSize: 12,
color: MyColors.lightTextColor,
),
10.height,
Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
price.toText(fontSize: 24, isBold: true),
2.width,
Padding(
padding: const EdgeInsets.only(bottom: 2),
child: "SAR".toText(
fontSize: 16,
isBold: true,
color: MyColors.lightTextColor),
),
],
)
],
),
),
],
).toContainer(
isShadowEnabled: true,
paddingAll: 16,
borderRadius: 0,
borderColor: isSelected ? MyColors.primaryColor : Colors.transparent,
isEnabledBorder: true,
borderWidget: 2,
);
}
}

@ -1,10 +1,17 @@
import 'package:car_provider_app/view_models/subscriptions_view_model.dart';
import 'package:car_provider_app/views/subscriptions/sheet/downgrade_data_sheet.dart';
import 'package:car_provider_app/views/subscriptions/sheet/upgrade_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/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/view_models/subscriptions_view_model.dart';
import 'package:mc_common_app/widgets/bottom_sheet.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';
@ -15,7 +22,10 @@ class SubscriptionsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
context.read<SubscriptionsVM>().getAllAvailableSubscriptions(null);
context.read<SubscriptionsVM>().getSubscriptionBySP(
AppState().getUser.data?.userInfo?.providerId.toString() ?? "",
true,
);
return Scaffold(
appBar: const CustomAppBar(
title: "Subscriptions",
@ -47,6 +57,21 @@ class SubscriptionsPage extends StatelessWidget {
return SubscriptionsCard(
model.tempSubscriptions[index],
isSubscribed: model.tempSubscriptions[index].isSubscribed ?? false,
isMainPage: false,
onRenewSubscriptionClick: () {
// context.read<PaymentVM>().updateOrderProviderSubscriptionId(id: model.tempSubscriptions[index].id??0);
// navigateWithName(
// context,
// AppRoutes.paymentMethodsView,
// arguments: PaymentTypes.subscription,
// );
if(model.tempSubscriptions[index].subscriptionTypeEnum==SubscriptionTypeEnum.upgrade){
showMyBottomSheet(context, child: UpgradePackageSheet(model.tempSubscriptions[index]));
}else{
showMyBottomSheet(context, child: DowngradeDataSheet(model.tempSubscriptions[index]));
}
},
);
},
separatorBuilder: (BuildContext context, int index) {

@ -1,129 +1,168 @@
import 'package:flutter/material.dart';
import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/subscriptions_models/subscription_model.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/date_helper.dart';
import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
class SubscriptionsCard extends StatelessWidget {
Subscription subscription;
bool isSubscribed;
Color? backgroundColor;
late Color textColor;
Function onRenewSubscriptionClick;
bool isMainPage;
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,
this.isMainPage = true})
: 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,
),
4.width,
Icon(
Icons.arrow_forward,
size: 16,
color: textColor,
)
],
)
],
),
if (isSubscribed)
// 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,
// ),
// )
if (!isMainPage)
if (subscription.subscriptionTypeEnum ==
SubscriptionTypeEnum.current)
"Current Package".toText(color: MyColors.primaryColor,fontWeight: FontWeight.bold),
if (isMainPage)
"Upgrade".toText(color: Colors.white).toContainer(
backgroundColor: MyColors.primaryColor,
borderRadius: 30,
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.start,
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 (!isMainPage)
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
(subscription.subscriptionTypeEnum ==
SubscriptionTypeEnum.current)
? "Renew".toText()
: (subscription.subscriptionTypeEnum)!
.getStringSubscriptionTypeEnum()
.toText(),
6.width,
const Icon(
Icons.arrow_forward,
size: 16,
)
],
),
],
)
],
).toWhiteContainer(
width: double.infinity,
allPading: 12,
backgroundColor: backgroundColor,
margin: const EdgeInsets.symmetric(
horizontal: 21,
),
// if (isSubscribed)
if (isMainPage)
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,
decorationColor: MyColors.primaryColor,
isBold: true,
),
],
).onPress(() {
onRenewSubscriptionClick();
}),
],
)
],
).toWhiteContainer(
width: double.infinity,
allPading: 12,
backgroundColor: backgroundColor,
margin: const EdgeInsets.symmetric(
horizontal: 21,
),
),
);
}

@ -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

Loading…
Cancel
Save