feat: filters added to home page
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
import 'package:food_delivery_client/feature/home/presentation/pages/categories_page/categories_page.dart';
|
||||
|
||||
import '../../../../../../food_delivery_client.dart';
|
||||
|
||||
class WDeliveryHeader extends StatelessWidget {
|
||||
@@ -13,55 +11,167 @@ class WDeliveryHeader extends StatelessWidget {
|
||||
context.loc.petSupplies,
|
||||
context.loc.more,
|
||||
];
|
||||
return Column(
|
||||
children: [
|
||||
15.verticalSpace,
|
||||
Row(
|
||||
spacing: 12,
|
||||
/*
|
||||
Siz uchun
|
||||
Eng ommabop,
|
||||
Reyting
|
||||
Yetkazib berish vaqti,
|
||||
Aksiyalar
|
||||
|
||||
|
||||
*/
|
||||
List titles = [
|
||||
'',
|
||||
context.loc.pickedForYou,
|
||||
context.loc.mostPopular,
|
||||
context.loc.rating,
|
||||
context.loc.deliveryTime,
|
||||
context.loc.deals,
|
||||
];
|
||||
return BlocBuilder<HomeBloc, HomeState>(
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
WCategoriesHeaderItem(
|
||||
onTap: () {},
|
||||
text: context.loc.american,
|
||||
imageUrl: AppImages.imgAmerican,
|
||||
),
|
||||
WCategoriesHeaderItem(
|
||||
onTap: () {},
|
||||
text: context.loc.grocery,
|
||||
imageUrl: AppImages.imgGrocery,
|
||||
Column(
|
||||
children: [
|
||||
15.verticalSpace,
|
||||
Row(
|
||||
spacing: 12,
|
||||
children: [
|
||||
WCategoriesHeaderItem(
|
||||
onTap: () {},
|
||||
text: context.loc.american,
|
||||
imageUrl: AppImages.imgAmerican,
|
||||
),
|
||||
WCategoriesHeaderItem(
|
||||
onTap: () {},
|
||||
text: context.loc.grocery,
|
||||
imageUrl: AppImages.imgGrocery,
|
||||
),
|
||||
],
|
||||
),
|
||||
8.verticalSpace,
|
||||
GridView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: _titles.length,
|
||||
padding: EdgeInsets.zero,
|
||||
scrollDirection: Axis.vertical,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
keyboardDismissBehavior:
|
||||
ScrollViewKeyboardDismissBehavior.onDrag,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 4,
|
||||
crossAxisSpacing: 5,
|
||||
mainAxisSpacing: 10,
|
||||
mainAxisExtent: 118,
|
||||
// childAspectRatio: 78 / 100,
|
||||
),
|
||||
itemBuilder: (context, index) => WCategoryItem(
|
||||
onTap: () {
|
||||
if (index == 3) {
|
||||
CategoriesPage().show(context);
|
||||
}
|
||||
},
|
||||
imgUrl: index != 3 ? _images[index] : null,
|
||||
text: _titles[index],
|
||||
child: index == 3
|
||||
? SizedBox(
|
||||
height: 55,
|
||||
width: 55,
|
||||
child: Icon(Icons.more_horiz),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddingSymmetric(horizontal: 15),
|
||||
15.verticalSpace,
|
||||
|
||||
SizedBox(
|
||||
height: 40,
|
||||
child: ListView.separated(
|
||||
padding: EdgeInsets.symmetric(horizontal: 15),
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: titles.length,
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
separatorBuilder: (context, index) => 10.horizontalSpace,
|
||||
itemBuilder: (context, index) => InkWell(
|
||||
onTap: () async {
|
||||
if (index != 3 && index != 0) {
|
||||
context.read<HomeBloc>().add(
|
||||
HomeEvent.filtered(titles[index]),
|
||||
);
|
||||
}
|
||||
|
||||
if (index == 3) {
|
||||
final response = await WRatingBottomSheet(
|
||||
savedRatings: state.rating ?? [],
|
||||
).show(context);
|
||||
|
||||
if (response != null) {
|
||||
context.read<HomeBloc>().add(
|
||||
HomeEvent.rated(response ?? []),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
borderRadius: AppUtils.kBorderRadius25,
|
||||
child: Ink(
|
||||
padding: EdgeInsets.zero,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.cEEEEEE,
|
||||
borderRadius: AppUtils.kBorderRadius25,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
if (index != 0 && state.filters.contains(titles[index]))
|
||||
SvgPicture.asset(
|
||||
AppIcons.icCheck1,
|
||||
).paddingOnly(right: 5),
|
||||
if (index == 0)
|
||||
Badge(
|
||||
isLabelVisible:
|
||||
state.filters.isNotEmpty ||
|
||||
state.rating.isNotEmpty,
|
||||
backgroundColor: AppColors.c34A853,
|
||||
child: SvgPicture.asset(AppIcons.icFilter),
|
||||
).paddingSymmetric(vertical: 6),
|
||||
|
||||
if (index == 3 && state.rating.isNotEmpty)
|
||||
SizedBox(
|
||||
height: 25,
|
||||
width: 25,
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.c34A853,
|
||||
borderRadius: AppUtils.kBorderRadius16,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
"${state.rating.length}",
|
||||
style: AppTextStyles.size14Regular.copyWith(
|
||||
color: AppColors.cFFFFFF,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
).paddingOnly(right: 8),
|
||||
Text(titles[index], style: AppTextStyles.size14Medium),
|
||||
if (index == 3) Icon(Icons.keyboard_arrow_down),
|
||||
],
|
||||
).paddingSymmetric(vertical: 0, horizontal: 15),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
10.verticalSpace,
|
||||
WDivider(),
|
||||
],
|
||||
),
|
||||
8.verticalSpace,
|
||||
GridView.builder(
|
||||
shrinkWrap: true,
|
||||
itemCount: _titles.length,
|
||||
padding: EdgeInsets.zero,
|
||||
scrollDirection: Axis.vertical,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 4,
|
||||
crossAxisSpacing: 5,
|
||||
mainAxisSpacing: 10,
|
||||
childAspectRatio: 78 / 100,
|
||||
),
|
||||
itemBuilder: (context, index) => WCategoryItem(
|
||||
onTap: () {
|
||||
if (index == 3) {
|
||||
CategoriesPage().show(context);
|
||||
}
|
||||
},
|
||||
imgUrl: index != 3 ? _images[index] : null,
|
||||
text: _titles[index],
|
||||
child: index == 3
|
||||
? SizedBox(height: 55, width: 55, child: Icon(Icons.more_horiz))
|
||||
: null,
|
||||
),
|
||||
),
|
||||
8.verticalSpace,
|
||||
WDivider()
|
||||
],
|
||||
).paddingSymmetric(horizontal: 15);
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ class WHomeHeader extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<HomeBloc, HomeState>(
|
||||
builder: (context, state) {
|
||||
|
||||
|
||||
return DecoratedBox(
|
||||
decoration: BoxDecoration(color: AppColors.cFFFFFF),
|
||||
child: Column(
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
import '../../../../../../food_delivery_client.dart';
|
||||
|
||||
class WRatingBottomSheet extends StatefulWidget {
|
||||
const WRatingBottomSheet({super.key, required this.savedRatings});
|
||||
|
||||
final List<String> savedRatings;
|
||||
|
||||
Future<List<String>?> show(BuildContext context) {
|
||||
return showModalBottomSheet<List<String>>(
|
||||
context: context,
|
||||
builder: (context) => Wrap(children: [this]),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
State<WRatingBottomSheet> createState() => _WRatingBottomSheetState();
|
||||
}
|
||||
|
||||
class _WRatingBottomSheetState extends State<WRatingBottomSheet> {
|
||||
List<String> rating = [];
|
||||
|
||||
void updateRating(String value) {
|
||||
final list = List<String>.from(rating);
|
||||
if (list.contains(value)) {
|
||||
list.remove(value);
|
||||
setState(() {
|
||||
rating = list;
|
||||
});
|
||||
} else {
|
||||
list.add(value);
|
||||
setState(() {
|
||||
rating = list;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
rating = widget.savedRatings;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<String> value = [
|
||||
"${context.loc.atLeast} 4,9",
|
||||
"${context.loc.atLeast} 4,7",
|
||||
"${context.loc.atLeast} 4,5",
|
||||
];
|
||||
|
||||
return WCustomModalBottomSheet(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(context.loc.rating, style: AppTextStyles.size20Medium),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
context.pop(null);
|
||||
},
|
||||
icon: SvgPicture.asset(AppIcons.icClose, height: 15),
|
||||
),
|
||||
],
|
||||
),
|
||||
15.verticalSpace,
|
||||
Wrap(
|
||||
spacing: 10,
|
||||
children: List.generate(value.length, (index) {
|
||||
return WRatingButton(
|
||||
onTap: () {
|
||||
updateRating(value[index]);
|
||||
},
|
||||
isActive: rating.contains(value[index]),
|
||||
rating: value[index],
|
||||
);
|
||||
}),
|
||||
),
|
||||
25.verticalSpace,
|
||||
AppButton(
|
||||
name: context.loc.apply,
|
||||
onPressed: () {
|
||||
context.pop(rating);
|
||||
},
|
||||
),
|
||||
20.verticalSpace,
|
||||
],
|
||||
).paddingSymmetric(horizontal: 15),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class WRatingButton extends StatelessWidget {
|
||||
const WRatingButton({
|
||||
super.key,
|
||||
required this.onTap,
|
||||
required this.isActive,
|
||||
required this.rating,
|
||||
});
|
||||
|
||||
final VoidCallback onTap;
|
||||
final bool isActive;
|
||||
final String rating;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
borderRadius: AppUtils.kBorderRadius25,
|
||||
onTap: onTap,
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
color: isActive
|
||||
? AppColors.c34A853
|
||||
: AppColors.cE6E6E6.newWithOpacity(.6),
|
||||
borderRadius: AppUtils.kBorderRadius25,
|
||||
),
|
||||
child: Row(
|
||||
spacing: 4,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.star, color: AppColors.cYellow),
|
||||
Text(
|
||||
rating,
|
||||
style: AppTextStyles.size14Medium.copyWith(
|
||||
color: isActive ? AppColors.cFFFFFF : AppColors.c000000,
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddingSymmetric(vertical: 6, horizontal: 10),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user