Compare commits

..

No commits in common. 'e5b29e859cbccddea07eb5ad6e06bd19216e739e' and '72b5a59bc1111dad75fad38b2d7ecc32d766ce1f' have entirely different histories.

@ -2,7 +2,6 @@ import 'package:car_customer_app/views/branches/branch_detail_view.dart';
import 'package:car_customer_app/views/branches/favourite_list_view.dart'; import 'package:car_customer_app/views/branches/favourite_list_view.dart';
import 'package:car_customer_app/views/branches/provider_profile_view.dart'; import 'package:car_customer_app/views/branches/provider_profile_view.dart';
import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/views/advertisement/favourite_ads_view.dart';
import 'package:mc_common_app/views/appointments/appointment_detail_view.dart'; import 'package:mc_common_app/views/appointments/appointment_detail_view.dart';
import 'package:mc_common_app/views/appointments/book_appointment_schedules_view.dart'; import 'package:mc_common_app/views/appointments/book_appointment_schedules_view.dart';
import 'package:mc_common_app/views/appointments/book_appointment_services_view.dart'; import 'package:mc_common_app/views/appointments/book_appointment_services_view.dart';
@ -30,8 +29,7 @@ class CustomerAppRoutes {
AppRoutes.branchSearchFilterPage: (context) => BranchesFilterView(), AppRoutes.branchSearchFilterPage: (context) => BranchesFilterView(),
AppRoutes.appoinmentSearchFilterPage: (context) => AppointmentsFilterView(), AppRoutes.appoinmentSearchFilterPage: (context) => AppointmentsFilterView(),
AppRoutes.providerProfileView: (context) => ProviderProfileView(providerId: ModalRoute.of(context)!.settings.arguments as int), AppRoutes.providerProfileView: (context) => ProviderProfileView(providerId: ModalRoute.of(context)!.settings.arguments as int),
AppRoutes.favoriteProvidersView: (context) => FavouriteProvidersView(), AppRoutes.favoriteListView: (context) => FavoriteListView(),
AppRoutes.favouriteAdsView: (context) => const FavouriteAdsView(),
}; };
} }

@ -170,3 +170,6 @@ class MyApp extends StatelessWidget {
); );
} }
} }

@ -18,14 +18,14 @@ import 'package:mc_common_app/widgets/common_widgets/provider_details_card.dart'
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class FavouriteProvidersView extends StatefulWidget { class FavoriteListView extends StatefulWidget {
const FavouriteProvidersView({Key? key}) : super(key: key); const FavoriteListView({Key? key}) : super(key: key);
@override @override
State<FavouriteProvidersView> createState() => _FavouriteProvidersViewState(); State<FavoriteListView> createState() => _FavoriteListViewState();
} }
class _FavouriteProvidersViewState extends State<FavouriteProvidersView> { class _FavoriteListViewState extends State<FavoriteListView> {
@override @override
void initState() { void initState() {
scheduleMicrotask(() async => context.read<AppointmentsVM>().getMyFavoriteProviders()); scheduleMicrotask(() async => context.read<AppointmentsVM>().getMyFavoriteProviders());

@ -15,7 +15,6 @@ import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/common_widgets/branch_details_card.dart'; import 'package:mc_common_app/widgets/common_widgets/branch_details_card.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:sizer/sizer.dart';
class ProviderProfileView extends StatefulWidget { class ProviderProfileView extends StatefulWidget {
final int providerId; final int providerId;
@ -50,6 +49,30 @@ class _ProviderProfileViewState extends State<ProviderProfileView> {
return Scaffold( return Scaffold(
appBar: CustomAppBar( appBar: CustomAppBar(
title: LocaleKeys.providerDetails.tr(), title: LocaleKeys.providerDetails.tr(),
actions: [
Icon(
appointmentsVM.providerProfileModel!.isFavorite! ? Icons.favorite : Icons.favorite_border,
color: appointmentsVM.providerProfileModel!.isFavorite! ? MyColors.darkPrimaryColor : MyColors.black,
).horPaddingMain().onPress(
() async {
if (appointmentsVM.providerProfileModel!.isFavorite!) {
bool status = await appointmentsVM.removeProviderFromFavorite(serviceProviderID: appointmentsVM.providerProfileModel!.id!, context: context);
if (status) {
appointmentsVM.providerProfileModel!.isFavorite = false;
appointmentsVM.getMyFavoriteProviders();
setState(() {});
}
} else {
bool status = await appointmentsVM.addProviderToFavorite(serviceProviderID: appointmentsVM.providerProfileModel!.id!, context: context);
if (status) {
appointmentsVM.providerProfileModel!.isFavorite = true;
setState(() {});
}
}
},
),
],
), ),
body: Container( body: Container(
width: double.infinity, width: double.infinity,
@ -61,28 +84,7 @@ class _ProviderProfileViewState extends State<ProviderProfileView> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Stack( Center(child: appointmentsVM.providerProfileModel!.profileImage.buildNetworkImage(height: 250, width: double.infinity, fit: BoxFit.cover)),
children: [
Center(
child: appointmentsVM.providerProfileModel!.profileImage.buildNetworkImage(
height: 250,
width: double.infinity,
fit: BoxFit.cover,
),
),
Positioned(
top: 10,
right: 10,
child: FavoriteProviderButton(
isFavorite: appointmentsVM.providerProfileModel!.isFavorite!,
serviceProviderID: appointmentsVM.providerProfileModel!.id!,
onToggle: () {
setState(() {});
},
),
),
],
),
12.height, 12.height,
if (appointmentsVM.providerProfileModel!.memberSince!.isNotEmpty) ...[ if (appointmentsVM.providerProfileModel!.memberSince!.isNotEmpty) ...[
Row( Row(
@ -164,121 +166,3 @@ class _ProviderProfileViewState extends State<ProviderProfileView> {
); );
} }
} }
class FavoriteProviderButton extends StatefulWidget {
final bool isFavorite;
final int serviceProviderID;
final VoidCallback onToggle;
const FavoriteProviderButton({
super.key,
required this.isFavorite,
required this.serviceProviderID,
required this.onToggle,
});
@override
State<FavoriteProviderButton> createState() => _FavoriteProviderButtonState();
}
class _FavoriteProviderButtonState extends State<FavoriteProviderButton> with SingleTickerProviderStateMixin {
bool isLoading = false;
late bool isFavorite;
late AnimationController _animationController;
late Animation<double> _scaleAnimation;
@override
void initState() {
super.initState();
isFavorite = widget.isFavorite;
_animationController = AnimationController(
duration: const Duration(milliseconds: 300),
vsync: this,
);
_scaleAnimation = Tween<double>(begin: 1.0, end: 1.3).animate(
CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
Future<void> toggleFavorite() async {
if (isLoading) return;
setState(() {
isLoading = true;
});
_animationController.forward().then((_) => _animationController.reverse());
bool success;
if (isFavorite) {
success = await context.read<AppointmentsVM>().removeProviderFromFavorite(serviceProviderID: widget.serviceProviderID);
} else {
success = await context.read<AppointmentsVM>().addProviderToFavorite(serviceProviderID: widget.serviceProviderID);
}
if (success) {
setState(() {
isFavorite = !isFavorite;
isLoading = false;
});
context.read<AppointmentsVM>().providerProfileModel!.isFavorite = isFavorite;
if (isFavorite == false) {
context.read<AppointmentsVM>().getMyFavoriteProviders();
}
widget.onToggle();
} else {
setState(() {
isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: toggleFavorite,
child: Container(
width: 8.6.w,
height: 8.6.w,
decoration: BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: const Color(0xff000000).withOpacity(.07),
blurRadius: 8,
offset: const Offset(0, 2),
),
],
),
child: Center(
child: isLoading
? SizedBox(
width: 4.4.w,
height: 4.4.w,
child: const CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(MyColors.darkPrimaryColor),
),
)
: ScaleTransition(
scale: _scaleAnimation,
child: Icon(
isFavorite ? Icons.favorite : Icons.favorite_border,
color: isFavorite ? Colors.red : MyColors.darkIconColor,
size: 5.5.w,
),
),
),
),
);
}
}

@ -15,7 +15,6 @@ import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/common_widgets/filters_list.dart'; import 'package:mc_common_app/widgets/common_widgets/filters_list.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/shimmer/home_shimmer_widgets.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
@ -71,10 +70,10 @@ class AppointmentsFragment extends StatelessWidget {
} }
}, },
child: appointmentsVM.state == ViewState.busy child: appointmentsVM.state == ViewState.busy
? const AppointmentsListShimmer(itemCount: 5) ? const Center(child: CircularProgressIndicator())
: appointmentsVM.myFilteredAppointmentsForCustomers.isEmpty : appointmentsVM.myFilteredAppointmentsForCustomers.isEmpty
? AppState().getIsViewOnly ? AppState().getIsViewOnly
? LocaleKeys.loginToViewAppointments.tr().toText(fontSize: 16, color: MyColors.lightTextColor) ? LocaleKeys.loginToViewAppointments.tr().toText(fontSize: 16, color: MyColors.lightTextColor)
: Column( : Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [

@ -14,7 +14,6 @@ import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/common_widgets/branch_details_card.dart'; import 'package:mc_common_app/widgets/common_widgets/branch_details_card.dart';
import 'package:mc_common_app/widgets/common_widgets/filters_list.dart'; import 'package:mc_common_app/widgets/common_widgets/filters_list.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/shimmer/home_shimmer_widgets.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class BranchesFragment extends StatelessWidget { class BranchesFragment extends StatelessWidget {
@ -67,7 +66,9 @@ class BranchesFragment extends StatelessWidget {
child: Container( child: Container(
width: double.infinity, width: double.infinity,
child: appointmentsVM.state == ViewState.busy child: appointmentsVM.state == ViewState.busy
? const BranchesListShimmer(itemCount: 5) ? const Center(
child: CircularProgressIndicator(),
)
: appointmentsVM.nearbyBranches.isEmpty : appointmentsVM.nearbyBranches.isEmpty
? Center( ? Center(
child: LocaleKeys.no_branch.tr().toText( child: LocaleKeys.no_branch.tr().toText(

@ -4,10 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/config/routes.dart'; import 'package:mc_common_app/config/routes.dart';
import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/generated/locale_keys.g.dart'; import 'package:mc_common_app/generated/locale_keys.g.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/utils/enums.dart'; import 'package:mc_common_app/utils/enums.dart';
import 'package:mc_common_app/utils/navigator.dart'; import 'package:mc_common_app/utils/navigator.dart';
import 'package:mc_common_app/view_models/ad_view_model.dart'; import 'package:mc_common_app/view_models/ad_view_model.dart';
@ -18,111 +15,11 @@ import 'package:mc_common_app/views/appointments/widgets/common_appointment_slid
import 'package:mc_common_app/widgets/common_widgets/app_bar.dart'; import 'package:mc_common_app/widgets/common_widgets/app_bar.dart';
import 'package:mc_common_app/widgets/common_widgets/view_all_widget.dart'; import 'package:mc_common_app/widgets/common_widgets/view_all_widget.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
import 'package:mc_common_app/widgets/shimmer/home_shimmer_widgets.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class HomeFragment extends StatefulWidget { class HomeFragment extends StatelessWidget {
const HomeFragment({Key? key}) : super(key: key); const HomeFragment({Key? key}) : super(key: key);
@override
State<HomeFragment> createState() => _HomeFragmentState();
}
class _HomeFragmentState extends State<HomeFragment> {
bool _isSearchingServices = false;
final TextEditingController _searchController = TextEditingController();
String _searchQuery = '';
@override
void dispose() {
_searchController.dispose();
super.dispose();
}
void _toggleSearch() {
setState(() {
_isSearchingServices = !_isSearchingServices;
if (!_isSearchingServices) {
_searchController.clear();
_searchQuery = '';
}
});
}
List<FilterListModel> _filterServices(List<FilterListModel> services) {
if (_searchQuery.isEmpty) {
return services;
}
return services.where((service) {
return service.title.toLowerCase().contains(_searchQuery.toLowerCase());
}).toList();
}
Widget _buildServicesHeader() {
if (_isSearchingServices) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 21),
child: Row(
children: [
Expanded(
child: Container(
height: 55,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey[300]!, width: 1),
),
child: TextField(
controller: _searchController,
autofocus: true,
style: const TextStyle(fontSize: 16),
onChanged: (value) {
setState(() {
_searchQuery = value;
});
},
decoration: InputDecoration(
hintText: LocaleKeys.searchService.tr(),
hintStyle: TextStyle(fontSize: 16, color: Colors.grey[600]),
prefixIcon: Icon(Icons.search, size: 26, color: Colors.grey[700]),
border: InputBorder.none,
contentPadding: const EdgeInsets.symmetric(horizontal: 18, vertical: 16),
),
),
),
),
14.width,
InkWell(
onTap: _toggleSearch,
child: Container(
height: 55,
width: 55,
decoration: BoxDecoration(
color: Colors.grey[200],
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey[300]!, width: 1),
),
child: Icon(Icons.close, size: 26, color: Colors.grey[700]),
),
),
],
),
);
} else {
return Row(
children: [
Expanded(
child: LocaleKeys.services.tr().toUpperCase().toText(fontSize: 20, isUpperCase: true, fontWeight: FontWeight.w600),
),
InkWell(
onTap: _toggleSearch,
child: const Icon(Icons.search, size: 28, color: MyColors.primaryColor),
),
],
).horPaddingMain();
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -172,64 +69,38 @@ class _HomeFragmentState extends State<HomeFragment> {
).horPaddingMain().toViewOnly(context, onTap: () { ).horPaddingMain().toViewOnly(context, onTap: () {
navigateWithName(context, AppRoutes.loginWithPassword, arguments: false); navigateWithName(context, AppRoutes.loginWithPassword, arguments: false);
}), }),
Consumer<AppointmentsVM>( CommonAppointmentSliderWidget()
builder: (BuildContext context, AppointmentsVM appointmentVM, Widget? child) { .toWhiteContainer(
// Show shimmer when loading width: double.infinity,
if (appointmentVM.state == ViewState.busy) { backgroundColor: Colors.transparent,
return const AppointmentSliderShimmer(); )
} .margin(left: 21, right: 21)
// Show actual data when idle .toViewOnly(context, onTap: () {
return CommonAppointmentSliderWidget() navigateWithName(context, AppRoutes.loginWithPassword, arguments: false);
.toWhiteContainer( }),
width: double.infinity,
backgroundColor: Colors.transparent,
)
.margin(left: 21, right: 21)
.toViewOnly(context, onTap: () {
navigateWithName(context, AppRoutes.loginWithPassword, arguments: false);
});
},
),
// SERVICES SECTION // SERVICES SECTION
14.height, 14.height,
Consumer( Consumer(
builder: (BuildContext context, AppointmentsVM appointmentVM, Widget? child) { builder: (BuildContext context, AppointmentsVM appointmentVM, Widget? child) {
// Show shimmer when loading
if (appointmentVM.state == ViewState.busy) { if (appointmentVM.state == ViewState.busy) {
return Column( return Center(child: CircularProgressIndicator());
children: [
_buildServicesHeader(),
14.height,
const ServicesGridShimmer(),
],
);
} }
// Show actual data when idle
if (appointmentVM.branchesCategoriesFilterOptions.isNotEmpty) { if (appointmentVM.branchesCategoriesFilterOptions.isNotEmpty) {
// Filter services based on search query
final filteredServices = _filterServices(appointmentVM.branchesCategoriesFilterOptions);
return Column( return Column(
children: [ children: [
_buildServicesHeader().toViewOnly(context, onTap: () { ViewAllWidget(
title: LocaleKeys.services.tr().toUpperCase(),
subTitle: '',
onSubtitleTapped: () {},
).horPaddingMain().toViewOnly(context, onTap: () {
navigateWithName(context, AppRoutes.loginWithPassword, arguments: false); navigateWithName(context, AppRoutes.loginWithPassword, arguments: false);
}), }),
14.height, MyServicesCategoriesWidget(homeCategories: appointmentVM.branchesCategoriesFilterOptions).horPaddingMain()
filteredServices.isEmpty
? Padding(
padding: const EdgeInsets.all(40),
child: LocaleKeys.noServiceFound.tr().toText(
fontSize: 16,
color: Colors.grey,
textAlign: TextAlign.center,
),
)
: MyServicesCategoriesWidget(homeCategories: filteredServices).horPaddingMain(),
], ],
); );
} }
return const SizedBox(); return SizedBox();
}, },
), ),
@ -279,22 +150,9 @@ class _HomeFragmentState extends State<HomeFragment> {
// ADS SECTION // ADS SECTION
Consumer( Consumer(
builder: (BuildContext context, AdVM adVM, Widget? child) { builder: (BuildContext context, AdVM adVM, Widget? child) {
// Show shimmer when loading
if (adVM.state == ViewState.busy) { if (adVM.state == ViewState.busy) {
return Column( return Center(child: CircularProgressIndicator());
children: [
15.height,
ViewAllWidget(
title: LocaleKeys.my_active_Ads.tr().toUpperCase(),
subTitle: LocaleKeys.view_all.tr(),
onSubtitleTapped: () {},
).horPaddingMain(),
14.height,
const AdsListShimmer(itemCount: 2),
],
);
} }
// Show actual data when idle
return Column( return Column(
children: [ children: [
if (adVM.myActiveAdsForHome.isNotEmpty) ...[ if (adVM.myActiveAdsForHome.isNotEmpty) ...[
@ -315,7 +173,7 @@ class _HomeFragmentState extends State<HomeFragment> {
shouldShowAdStatus: true, shouldShowAdStatus: true,
isAdsFragment: false, isAdsFragment: false,
adsList: adVM.myActiveAdsForHome, adsList: adVM.myActiveAdsForHome,
scrollPhysics: const NeverScrollableScrollPhysics(), scrollPhysics: NeverScrollableScrollPhysics(),
hasMoreData: adVM.isExploreAdsTapped ? adVM.hasMoreDataForExploreAds : adVM.hasMoreDataForMyAds, hasMoreData: adVM.isExploreAdsTapped ? adVM.hasMoreDataForExploreAds : adVM.hasMoreDataForMyAds,
).toViewOnly(context, onTap: () { ).toViewOnly(context, onTap: () {
navigateWithName(context, AppRoutes.loginWithPassword, arguments: false); navigateWithName(context, AppRoutes.loginWithPassword, arguments: false);
@ -323,31 +181,30 @@ class _HomeFragmentState extends State<HomeFragment> {
], ],
) )
], ],
// RECOMMENDED ADS SECTION - COMMENTED OUT if (adVM.exploreAds.isNotEmpty) ...[
// if (adVM.exploreAds.isNotEmpty) ...[ Column(
// Column( children: [
// children: [ 15.height,
// 15.height, ViewAllWidget(
// ViewAllWidget( title: LocaleKeys.myRecommendedAds.tr().toUpperCase(),
// title: LocaleKeys.myRecommendedAds.tr().toUpperCase(), subTitle: LocaleKeys.view_all.tr(),
// subTitle: LocaleKeys.view_all.tr(), onSubtitleTapped: () {
// onSubtitleTapped: () { context.read<DashboardVmCustomer>().onNavbarTapped(3);
// context.read<DashboardVmCustomer>().onNavbarTapped(3); context.read<AdVM>().updateIsExploreAds(true);
// context.read<AdVM>().updateIsExploreAds(true); context.read<AdVM>().applyFilterOnExploreAds(vehicleBrandId: 0);
// context.read<AdVM>().applyFilterOnExploreAds(vehicleBrandId: 0); },
// }, ).horPaddingMain(),
// ).horPaddingMain(), AdsListWidget(
// AdsListWidget( isDraftAds: false,
// isDraftAds: false, shouldShowAdStatus: false,
// shouldShowAdStatus: false, adsList: adVM.exploreAds.length >= 3 ? adVM.exploreAds.take(3).toList() : adVM.exploreAds,
// adsList: adVM.exploreAds.length >= 3 ? adVM.exploreAds.take(3).toList() : adVM.exploreAds, isAdsFragment: false,
// isAdsFragment: false, scrollPhysics: NeverScrollableScrollPhysics(),
// scrollPhysics: NeverScrollableScrollPhysics(), hasMoreData: adVM.isExploreAdsTapped ? adVM.hasMoreDataForExploreAds : adVM.hasMoreDataForMyAds,
// hasMoreData: adVM.isExploreAdsTapped ? adVM.hasMoreDataForExploreAds : adVM.hasMoreDataForMyAds, ),
// ), ],
// ], )
// ) ]
// ]
], ],
); );
}, },

@ -1,10 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/classes/consts.dart';
import 'package:mc_common_app/extensions/int_extensions.dart'; import 'package:mc_common_app/extensions/int_extensions.dart';
import 'package:mc_common_app/extensions/string_extensions.dart'; import 'package:mc_common_app/extensions/string_extensions.dart';
import 'package:mc_common_app/models/general_models/widgets_models.dart'; import 'package:mc_common_app/models/general_models/widgets_models.dart';
import 'package:mc_common_app/theme/colors.dart';
import 'package:mc_common_app/view_models/appointments_view_model.dart'; import 'package:mc_common_app/view_models/appointments_view_model.dart';
import 'package:mc_common_app/view_models/dashboard_view_model_customer.dart'; import 'package:mc_common_app/view_models/dashboard_view_model_customer.dart';
import 'package:mc_common_app/widgets/extensions/extensions_widget.dart'; import 'package:mc_common_app/widgets/extensions/extensions_widget.dart';
@ -17,89 +14,45 @@ class MyServicesCategoriesWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final isArabic = AppState().isArabic(context); return SizedBox(
// Filter out categories with id == 0 width: double.infinity,
final filteredCategories = homeCategories.where((category) => category.id != 0).toList(); height: 140,
child: ListView.builder(
// Define background colors to cycle through itemCount: homeCategories.length,
final List<Color> bgColors = [ scrollDirection: Axis.horizontal,
const Color(0xFFF3F4F6), // Light gray shrinkWrap: true,
const Color(0xFFFEF4E9), // Light cream/orange itemBuilder: (BuildContext context, int index) {
const Color(0xFFE5EEE5), // Light green FilterListModel category = homeCategories[index];
const Color(0xFFF0EFF5), // Light purple if (category.id == 0) {
]; return SizedBox();
}
return GridView.builder( return SizedBox(
shrinkWrap: true, width: 90,
physics: const NeverScrollableScrollPhysics(), child: Column(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( children: [
crossAxisCount: 3, category.iconUrl.buildNetworkImage(height: 73, width: 73, fit: BoxFit.cover).toCircle(borderRadius: 100),
mainAxisSpacing: 12, 9.height,
crossAxisSpacing: 12,
childAspectRatio: 0.9,
),
itemCount: filteredCategories.length,
itemBuilder: (BuildContext context, int index) {
FilterListModel category = filteredCategories[index];
// Cycle through colors based on index
Color bgColor = bgColors[index % bgColors.length];
return Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: bgColor,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.04),
blurRadius: 4,
offset: const Offset(0, 2),
),
],
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
category.isCustom ? category.iconUrl.buildNetworkImage(height: 32, width: 32, fit: BoxFit.fill) : category.iconUrl.buildNetworkImage(height: 32, width: 32, fit: BoxFit.fill),
10.height,
Flexible(
child: (isArabic ? category.titleN : category.title).toText(
fontSize: 16,
fontWeight: FontWeight.w600,
maxLines: 3,
overflow: TextOverflow.ellipsis,
height: 1.2,
),
),
if (category.description.isNotEmpty || category.descriptionN.isNotEmpty) ...[
6.height,
Flexible( Flexible(
child: (category.description).toText( child: category.title.toText(
fontSize: 10, fontSize: 14,
fontWeight: FontWeight.w600, textAlign: TextAlign.center,
maxLines: 3, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
height: 1.2, letterSpacing: -0.84,
height: 18 / 14,
), ),
), ),
], ],
10.height, ),
Row( ).onPress(() {
mainAxisAlignment: MainAxisAlignment.end, final appointmentVM = context.read<AppointmentsVM>();
children: [MyAssets.arrowRight.buildSvg()], final dashboardCustomerVM = context.read<DashboardVmCustomer>();
), context.read<DashboardVmCustomer>().onNavbarTapped(0);
], dashboardCustomerVM.onNavbarTapped(0);
), appointmentVM.applyFilterOnBranches(index: index);
).onPress(() { });
final appointmentVM = context.read<AppointmentsVM>(); },
final dashboardCustomerVM = context.read<DashboardVmCustomer>(); ),
context.read<DashboardVmCustomer>().onNavbarTapped(0);
dashboardCustomerVM.onNavbarTapped(0);
// Use the original index from homeCategories for filtering
int originalIndex = homeCategories.indexOf(category);
appointmentVM.applyFilterOnBranches(index: originalIndex);
});
},
); );
} }
} }

@ -36,10 +36,10 @@ dependencies:
cupertino_icons: ^1.0.2 cupertino_icons: ^1.0.2
mc_common_app: mc_common_app:
path: /Volumes/Data/Projects/Flutter_Projects/mowater_apps/car_common_app # path: /Volumes/Data/Projects/Flutter_Projects/car_common_app
# path: /Users/faizhashmi/Development/Projects/MyProjects/CloudSolutions/car_common_app # path: /Users/faizhashmi/Development/Projects/MyProjects/CloudSolutions/car_common_app
# path: /Users/aamir/StudioProjects/car_common_app # path: /Users/aamir/StudioProjects/car_common_app
# path: C:/dev/Mawater/car_common_app path: C:/dev/Mawater/car_common_app
dev_dependencies: dev_dependencies:

Loading…
Cancel
Save