feat:filters done

This commit is contained in:
jahongireshonqulov
2025-10-24 18:06:43 +05:00
parent f2ab615b4e
commit e0f3d900d7
30 changed files with 635 additions and 44 deletions

View File

@@ -0,0 +1,44 @@
import '../../../../food_delivery_client.dart';
class AppListTile extends StatelessWidget {
const AppListTile({
super.key,
required this.onPressed,
required this.isSelected,
required this.svgPath,
required this.title,
this.contentPadding,
this.leading,
this.titleWidget,
this.trailing,
this.titleTextStyle,
this.subTitle,
});
final VoidCallback onPressed;
final bool isSelected;
final String svgPath;
final String title;
final EdgeInsets? contentPadding;
final Widget? leading;
final Widget? titleWidget;
final Widget? trailing;
final TextStyle? titleTextStyle;
final Widget? subTitle;
@override
Widget build(BuildContext context) {
return ListTile(
onTap: onPressed,
subtitle: subTitle,
contentPadding:
contentPadding ?? EdgeInsetsGeometry.only(left: 20, right: 27),
leading: leading ?? SvgPicture.asset(svgPath),
title:
titleWidget ??
Text(title, style: titleTextStyle ?? AppTextStyles.size16Regular),
trailing:
trailing ?? (isSelected ? SvgPicture.asset(AppIcons.icCheck) : null),
);
}
}

View File

@@ -5,3 +5,4 @@ export 'w_see_all_raw.dart';
export 'w_stories_list_item.dart';
export 'w_custom_modal_bottom_sheet.dart';
export 'app_button.dart';
export 'app_list_tile.dart';

View File

@@ -12,3 +12,11 @@ export 'package:food_delivery_client/feature/home/presentation/pages/home_page/w
export 'package:flutter_svg/flutter_svg.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/categories_page/categories_page.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/home_page/widgets/w_rating_btm_sheet.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/filters_page.dart';
export 'presentation/mixins/filter_mixins.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_filter_app_bar.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_filters_body.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_delivery_duration.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_filter_dietary.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_filters_deals.dart';
export 'package:food_delivery_client/feature/home/presentation/pages/filters_page/widgets/w_filters_sort.dart';

View File

@@ -12,6 +12,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
on<_Changed>(_onChanged);
on<_Filtered>(_onFiltered);
on<_Rated>(_onRated);
on<_DurationChanged>(_onDurationChanged);
}
void _onChanged(_Changed event, Emitter<HomeState> emit) {
@@ -29,9 +30,11 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
}
}
void _onRated(_Rated event, Emitter<HomeState> emit){
void _onRated(_Rated event, Emitter<HomeState> emit) {
emit(state.copyWith(rating: event.filter));
}
void _onDurationChanged(_DurationChanged event, Emitter<HomeState> emit) {
emit(state.copyWith(deliveryDuration: event.filter));
}
}

View File

@@ -55,12 +55,13 @@ extension HomeEventPatterns on HomeEvent {
/// }
/// ```
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _Started value)? started,TResult Function( _Changed value)? changed,TResult Function( _Filtered value)? filtered,TResult Function( _Rated value)? rated,required TResult orElse(),}){
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _Started value)? started,TResult Function( _Changed value)? changed,TResult Function( _DurationChanged value)? durationChanged,TResult Function( _Filtered value)? filtered,TResult Function( _Rated value)? rated,required TResult orElse(),}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _Changed() when changed != null:
return changed(_that);case _Filtered() when filtered != null:
return changed(_that);case _DurationChanged() when durationChanged != null:
return durationChanged(_that);case _Filtered() when filtered != null:
return filtered(_that);case _Rated() when rated != null:
return rated(_that);case _:
return orElse();
@@ -80,12 +81,13 @@ return rated(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _Started value) started,required TResult Function( _Changed value) changed,required TResult Function( _Filtered value) filtered,required TResult Function( _Rated value) rated,}){
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _Started value) started,required TResult Function( _Changed value) changed,required TResult Function( _DurationChanged value) durationChanged,required TResult Function( _Filtered value) filtered,required TResult Function( _Rated value) rated,}){
final _that = this;
switch (_that) {
case _Started():
return started(_that);case _Changed():
return changed(_that);case _Filtered():
return changed(_that);case _DurationChanged():
return durationChanged(_that);case _Filtered():
return filtered(_that);case _Rated():
return rated(_that);case _:
throw StateError('Unexpected subclass');
@@ -104,12 +106,13 @@ return rated(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _Started value)? started,TResult? Function( _Changed value)? changed,TResult? Function( _Filtered value)? filtered,TResult? Function( _Rated value)? rated,}){
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _Started value)? started,TResult? Function( _Changed value)? changed,TResult? Function( _DurationChanged value)? durationChanged,TResult? Function( _Filtered value)? filtered,TResult? Function( _Rated value)? rated,}){
final _that = this;
switch (_that) {
case _Started() when started != null:
return started(_that);case _Changed() when changed != null:
return changed(_that);case _Filtered() when filtered != null:
return changed(_that);case _DurationChanged() when durationChanged != null:
return durationChanged(_that);case _Filtered() when filtered != null:
return filtered(_that);case _Rated() when rated != null:
return rated(_that);case _:
return null;
@@ -128,11 +131,12 @@ return rated(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? started,TResult Function( int index)? changed,TResult Function( String filter)? filtered,TResult Function( List<String> filter)? rated,required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? started,TResult Function( int index)? changed,TResult Function( String filter)? durationChanged,TResult Function( String filter)? filtered,TResult Function( List<String> filter)? rated,required TResult orElse(),}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _Changed() when changed != null:
return changed(_that.index);case _Filtered() when filtered != null:
return changed(_that.index);case _DurationChanged() when durationChanged != null:
return durationChanged(_that.filter);case _Filtered() when filtered != null:
return filtered(_that.filter);case _Rated() when rated != null:
return rated(_that.filter);case _:
return orElse();
@@ -152,11 +156,12 @@ return rated(_that.filter);case _:
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() started,required TResult Function( int index) changed,required TResult Function( String filter) filtered,required TResult Function( List<String> filter) rated,}) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() started,required TResult Function( int index) changed,required TResult Function( String filter) durationChanged,required TResult Function( String filter) filtered,required TResult Function( List<String> filter) rated,}) {final _that = this;
switch (_that) {
case _Started():
return started();case _Changed():
return changed(_that.index);case _Filtered():
return changed(_that.index);case _DurationChanged():
return durationChanged(_that.filter);case _Filtered():
return filtered(_that.filter);case _Rated():
return rated(_that.filter);case _:
throw StateError('Unexpected subclass');
@@ -175,11 +180,12 @@ return rated(_that.filter);case _:
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? started,TResult? Function( int index)? changed,TResult? Function( String filter)? filtered,TResult? Function( List<String> filter)? rated,}) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? started,TResult? Function( int index)? changed,TResult? Function( String filter)? durationChanged,TResult? Function( String filter)? filtered,TResult? Function( List<String> filter)? rated,}) {final _that = this;
switch (_that) {
case _Started() when started != null:
return started();case _Changed() when changed != null:
return changed(_that.index);case _Filtered() when filtered != null:
return changed(_that.index);case _DurationChanged() when durationChanged != null:
return durationChanged(_that.filter);case _Filtered() when filtered != null:
return filtered(_that.filter);case _Rated() when rated != null:
return rated(_that.filter);case _:
return null;
@@ -290,6 +296,72 @@ as int,
/// @nodoc
class _DurationChanged implements HomeEvent {
const _DurationChanged(this.filter);
final String filter;
/// Create a copy of HomeEvent
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@pragma('vm:prefer-inline')
_$DurationChangedCopyWith<_DurationChanged> get copyWith => __$DurationChangedCopyWithImpl<_DurationChanged>(this, _$identity);
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _DurationChanged&&(identical(other.filter, filter) || other.filter == filter));
}
@override
int get hashCode => Object.hash(runtimeType,filter);
@override
String toString() {
return 'HomeEvent.durationChanged(filter: $filter)';
}
}
/// @nodoc
abstract mixin class _$DurationChangedCopyWith<$Res> implements $HomeEventCopyWith<$Res> {
factory _$DurationChangedCopyWith(_DurationChanged value, $Res Function(_DurationChanged) _then) = __$DurationChangedCopyWithImpl;
@useResult
$Res call({
String filter
});
}
/// @nodoc
class __$DurationChangedCopyWithImpl<$Res>
implements _$DurationChangedCopyWith<$Res> {
__$DurationChangedCopyWithImpl(this._self, this._then);
final _DurationChanged _self;
final $Res Function(_DurationChanged) _then;
/// Create a copy of HomeEvent
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') $Res call({Object? filter = null,}) {
return _then(_DurationChanged(
null == filter ? _self.filter : filter // ignore: cast_nullable_to_non_nullable
as String,
));
}
}
/// @nodoc
class _Filtered implements HomeEvent {
const _Filtered(this.filter);
@@ -428,7 +500,7 @@ as List<String>,
/// @nodoc
mixin _$HomeState {
int get currentIndex; List get filters; List<String> get rating;
int get currentIndex; String get deliveryDuration; List get filters; List<String> get rating;
/// Create a copy of HomeState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -439,16 +511,16 @@ $HomeStateCopyWith<HomeState> get copyWith => _$HomeStateCopyWithImpl<HomeState>
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is HomeState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex)&&const DeepCollectionEquality().equals(other.filters, filters)&&const DeepCollectionEquality().equals(other.rating, rating));
return identical(this, other) || (other.runtimeType == runtimeType&&other is HomeState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex)&&(identical(other.deliveryDuration, deliveryDuration) || other.deliveryDuration == deliveryDuration)&&const DeepCollectionEquality().equals(other.filters, filters)&&const DeepCollectionEquality().equals(other.rating, rating));
}
@override
int get hashCode => Object.hash(runtimeType,currentIndex,const DeepCollectionEquality().hash(filters),const DeepCollectionEquality().hash(rating));
int get hashCode => Object.hash(runtimeType,currentIndex,deliveryDuration,const DeepCollectionEquality().hash(filters),const DeepCollectionEquality().hash(rating));
@override
String toString() {
return 'HomeState(currentIndex: $currentIndex, filters: $filters, rating: $rating)';
return 'HomeState(currentIndex: $currentIndex, deliveryDuration: $deliveryDuration, filters: $filters, rating: $rating)';
}
@@ -459,7 +531,7 @@ abstract mixin class $HomeStateCopyWith<$Res> {
factory $HomeStateCopyWith(HomeState value, $Res Function(HomeState) _then) = _$HomeStateCopyWithImpl;
@useResult
$Res call({
int currentIndex, List filters, List<String> rating
int currentIndex, String deliveryDuration, List filters, List<String> rating
});
@@ -476,10 +548,11 @@ class _$HomeStateCopyWithImpl<$Res>
/// Create a copy of HomeState
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? currentIndex = null,Object? filters = null,Object? rating = null,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? currentIndex = null,Object? deliveryDuration = null,Object? filters = null,Object? rating = null,}) {
return _then(_self.copyWith(
currentIndex: null == currentIndex ? _self.currentIndex : currentIndex // ignore: cast_nullable_to_non_nullable
as int,filters: null == filters ? _self.filters : filters // ignore: cast_nullable_to_non_nullable
as int,deliveryDuration: null == deliveryDuration ? _self.deliveryDuration : deliveryDuration // ignore: cast_nullable_to_non_nullable
as String,filters: null == filters ? _self.filters : filters // ignore: cast_nullable_to_non_nullable
as List,rating: null == rating ? _self.rating : rating // ignore: cast_nullable_to_non_nullable
as List<String>,
));
@@ -566,10 +639,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int currentIndex, List filters, List<String> rating)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int currentIndex, String deliveryDuration, List filters, List<String> rating)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _HomeState() when $default != null:
return $default(_that.currentIndex,_that.filters,_that.rating);case _:
return $default(_that.currentIndex,_that.deliveryDuration,_that.filters,_that.rating);case _:
return orElse();
}
@@ -587,10 +660,10 @@ return $default(_that.currentIndex,_that.filters,_that.rating);case _:
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int currentIndex, List filters, List<String> rating) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int currentIndex, String deliveryDuration, List filters, List<String> rating) $default,) {final _that = this;
switch (_that) {
case _HomeState():
return $default(_that.currentIndex,_that.filters,_that.rating);case _:
return $default(_that.currentIndex,_that.deliveryDuration,_that.filters,_that.rating);case _:
throw StateError('Unexpected subclass');
}
@@ -607,10 +680,10 @@ return $default(_that.currentIndex,_that.filters,_that.rating);case _:
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int currentIndex, List filters, List<String> rating)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int currentIndex, String deliveryDuration, List filters, List<String> rating)? $default,) {final _that = this;
switch (_that) {
case _HomeState() when $default != null:
return $default(_that.currentIndex,_that.filters,_that.rating);case _:
return $default(_that.currentIndex,_that.deliveryDuration,_that.filters,_that.rating);case _:
return null;
}
@@ -622,10 +695,11 @@ return $default(_that.currentIndex,_that.filters,_that.rating);case _:
class _HomeState implements HomeState {
const _HomeState({this.currentIndex = 0, final List filters = const [], final List<String> rating = const []}): _filters = filters,_rating = rating;
const _HomeState({this.currentIndex = 0, this.deliveryDuration = "60+", final List filters = const [], final List<String> rating = const []}): _filters = filters,_rating = rating;
@override@JsonKey() final int currentIndex;
@override@JsonKey() final String deliveryDuration;
final List _filters;
@override@JsonKey() List get filters {
if (_filters is EqualUnmodifiableListView) return _filters;
@@ -651,16 +725,16 @@ _$HomeStateCopyWith<_HomeState> get copyWith => __$HomeStateCopyWithImpl<_HomeSt
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _HomeState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex)&&const DeepCollectionEquality().equals(other._filters, _filters)&&const DeepCollectionEquality().equals(other._rating, _rating));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _HomeState&&(identical(other.currentIndex, currentIndex) || other.currentIndex == currentIndex)&&(identical(other.deliveryDuration, deliveryDuration) || other.deliveryDuration == deliveryDuration)&&const DeepCollectionEquality().equals(other._filters, _filters)&&const DeepCollectionEquality().equals(other._rating, _rating));
}
@override
int get hashCode => Object.hash(runtimeType,currentIndex,const DeepCollectionEquality().hash(_filters),const DeepCollectionEquality().hash(_rating));
int get hashCode => Object.hash(runtimeType,currentIndex,deliveryDuration,const DeepCollectionEquality().hash(_filters),const DeepCollectionEquality().hash(_rating));
@override
String toString() {
return 'HomeState(currentIndex: $currentIndex, filters: $filters, rating: $rating)';
return 'HomeState(currentIndex: $currentIndex, deliveryDuration: $deliveryDuration, filters: $filters, rating: $rating)';
}
@@ -671,7 +745,7 @@ abstract mixin class _$HomeStateCopyWith<$Res> implements $HomeStateCopyWith<$Re
factory _$HomeStateCopyWith(_HomeState value, $Res Function(_HomeState) _then) = __$HomeStateCopyWithImpl;
@override @useResult
$Res call({
int currentIndex, List filters, List<String> rating
int currentIndex, String deliveryDuration, List filters, List<String> rating
});
@@ -688,10 +762,11 @@ class __$HomeStateCopyWithImpl<$Res>
/// Create a copy of HomeState
/// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? currentIndex = null,Object? filters = null,Object? rating = null,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? currentIndex = null,Object? deliveryDuration = null,Object? filters = null,Object? rating = null,}) {
return _then(_HomeState(
currentIndex: null == currentIndex ? _self.currentIndex : currentIndex // ignore: cast_nullable_to_non_nullable
as int,filters: null == filters ? _self._filters : filters // ignore: cast_nullable_to_non_nullable
as int,deliveryDuration: null == deliveryDuration ? _self.deliveryDuration : deliveryDuration // ignore: cast_nullable_to_non_nullable
as String,filters: null == filters ? _self._filters : filters // ignore: cast_nullable_to_non_nullable
as List,rating: null == rating ? _self._rating : rating // ignore: cast_nullable_to_non_nullable
as List<String>,
));

View File

@@ -4,6 +4,7 @@ part of 'home_bloc.dart';
class HomeEvent with _$HomeEvent {
const factory HomeEvent.started() = _Started;
const factory HomeEvent.changed(int index) = _Changed;
const factory HomeEvent.durationChanged(String filter) = _DurationChanged;
const factory HomeEvent.filtered(String filter) = _Filtered;
const factory HomeEvent.rated(List<String> filter) = _Rated;

View File

@@ -4,6 +4,7 @@ part of 'home_bloc.dart';
abstract class HomeState with _$HomeState {
const factory HomeState({
@Default(0) int currentIndex,
@Default("60+") String deliveryDuration,
@Default([]) List filters,
@Default([]) List<String> rating

View File

@@ -0,0 +1,20 @@
import '../../../../core/theme/app_icons.dart';
mixin FilterMixins {
final List<String> deliveryDurations = ["30", "45", "60", "60+"];
final List<String> filterSortSvgs = [
AppIcons.icPicked,
AppIcons.icMostPopular,
AppIcons.icStar,
AppIcons.icDeliveryTime,
];
final List<String> filterDietary = [
AppIcons.icVegetarian,
AppIcons.icVegen,
AppIcons.icGlutenFree,
AppIcons.icAllergyFriendly,
];
final List<String> filterDeals = [AppIcons.icDeals, AppIcons.icBestOverall];
}

View File

@@ -0,0 +1,26 @@
import '../../../../../food_delivery_client.dart';
class FiltersPage extends StatefulWidget {
const FiltersPage({super.key, required this.homeBloc});
final HomeBloc homeBloc;
@override
State<FiltersPage> createState() => _FiltersPageState();
}
class _FiltersPageState extends State<FiltersPage> {
@override
Widget build(BuildContext context) {
return BlocProvider.value(
value: widget.homeBloc,
child: BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
return WFiltersBody();
},
),
);
}
}

View File

@@ -0,0 +1,84 @@
import '../../../../../../food_delivery_client.dart';
class WDeliveryDuration extends StatelessWidget with FilterMixins {
WDeliveryDuration({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.loc.delivery,
style: AppTextStyles.size18Medium,
).paddingSymmetric(horizontal: 20),
15.verticalSpace,
SizedBox(
height: 60,
child: Stack(
alignment: AlignmentGeometry.center,
children: [
SizedBox(
height: 40,
width: context.w,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: AppUtils.kBorderRadius8,
color: AppColors.cE6E6E6.newWithOpacity(.6),
),
),
),
Material(
color: AppColors.cTransparent,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(deliveryDurations.length, (
index,
) {
final isActive =
state.deliveryDuration == deliveryDurations[index];
return InkWell(
onTap: () {
context.read<HomeBloc>().add(
HomeEvent.durationChanged(
deliveryDurations[index],
),
);
},
borderRadius: AppUtils.kBorderRadius40,
child: Ink(
height: 60,
width: 60,
decoration: BoxDecoration(
color: isActive
? AppColors.c34A853
: AppColors.cTransparent,
borderRadius: AppUtils.kBorderRadius40,
),
child: Center(
child: Text(
deliveryDurations[index],
style: AppTextStyles.size16Medium.copyWith(
color: isActive
? AppColors.cFFFFFF
: AppColors.c000000,
),
),
),
),
);
}),
),
),
],
),
).paddingSymmetric(horizontal: 20),
25.verticalSpace,
],
);
},
);
}
}

View File

@@ -0,0 +1,25 @@
import '../../../../../../food_delivery_client.dart';
class WFiltersAppBar extends StatelessWidget {
const WFiltersAppBar({super.key});
@override
Widget build(BuildContext context) {
return AppBar(
centerTitle: true,
elevation: 30,
bottomOpacity: 1,
scrolledUnderElevation: 10,
backgroundColor: AppColors.cFFFFFF,
surfaceTintColor: AppColors.cTransparent,
useDefaultSemanticsOrder: true,
leading: IconButton(
onPressed: () {
context.pop();
},
icon: SvgPicture.asset(AppIcons.icClose),
),
title: Text(context.loc.allCategories, style: AppTextStyles.size20Medium),
);
}
}

View File

@@ -0,0 +1,38 @@
import '../../../../../../food_delivery_client.dart';
class WFilterDietary extends StatelessWidget with FilterMixins {
WFilterDietary({super.key});
@override
Widget build(BuildContext context) {
final List<String> dietaryTitles = [
context.loc.vegetarian,
context.loc.vegan,
context.loc.glutenFree,
context.loc.allergyFriendly,
];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
25.verticalSpace,
Text(
context.loc.dietary,
style: AppTextStyles.size18Medium,
).paddingSymmetric(horizontal: 20),
15.verticalSpace,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: List.generate(4, (index) {
return AppListTile(
onPressed: () {},
isSelected: false,
leading: Image.asset(filterDietary[index], height: 30, width: 30),
svgPath: filterDietary[index],
title: dietaryTitles[index],
);
}),
),
],
);
}
}

View File

@@ -0,0 +1,42 @@
import '../../../../../../food_delivery_client.dart';
class WFiltersBody extends StatelessWidget {
const WFiltersBody({super.key});
@override
Widget build(BuildContext context) {
return BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
return WLayout(
child: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(56),
child: WFiltersAppBar(),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
18.verticalSpace,
WDeliveryDuration(),
WFiltersSort(),
WFiltersDeals(),
WFilterDietary(),
],
),
),
),
],
),
),
);
},
);
}
}

View File

@@ -0,0 +1,59 @@
import 'package:flutter/cupertino.dart';
import '../../../../../../food_delivery_client.dart';
class WFiltersDeals extends StatefulWidget {
const WFiltersDeals({super.key});
@override
State<WFiltersDeals> createState() => _WFiltersDealsState();
}
class _WFiltersDealsState extends State<WFiltersDeals> with FilterMixins {
List<bool> values = [false, false];
@override
Widget build(BuildContext context) {
final List<String> dealsTitle = [
context.loc.deals,
context.loc.bestOverall,
];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
25.verticalSpace,
Text(
"From Uber eats",
style: AppTextStyles.size18Medium,
).paddingSymmetric(horizontal: 20),
15.verticalSpace,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: List.generate(2, (index) {
return AppListTile(
onPressed: () {
setState(() {
values[index] = !values[index];
});
},
isSelected: false,
leading: index == 0
? SvgPicture.asset(filterDeals[index], height: 30, width: 30)
: Image.asset(filterDeals[index], height: 30, width: 30),
svgPath: filterDeals[index],
title: dealsTitle[index],
trailing: CupertinoSwitch(
value: values[index],
onChanged: (value) {
setState(() {
values[index] = !values[index];
});
},
),
);
}),
),
],
);
}
}

View File

@@ -0,0 +1,60 @@
import '../../../../../../food_delivery_client.dart';
class WFiltersSort extends StatelessWidget with FilterMixins {
WFiltersSort({super.key});
@override
Widget build(BuildContext context) {
final List<String> filterSortTitles = [
context.loc.pickedForYouDefault,
context.loc.mostPopular,
context.loc.topRated,
context.loc.fast,
];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.loc.sort,
style: AppTextStyles.size18Medium,
).paddingSymmetric(horizontal: 20),
15.verticalSpace,
Column(
children: List.generate(filterSortTitles.length, (index) {
return AppListTile(
onPressed: () {},
isSelected: false,
svgPath: filterSortSvgs[index],
title: filterSortTitles[index],
);
}),
),
// AppListTile(
// onPressed: () {},
// isSelected: true,
// svgPath: AppIcons.icPicked,
// title: context.loc.pickedForYouDefault,
// ),
// AppListTile(
// onPressed: () {},
// isSelected: false,
// svgPath: AppIcons.icMostPopular,
// title: context.loc.popular,
// ),
// AppListTile(
// onPressed: () {},
// isSelected: false,
// svgPath: AppIcons.icStar,
// title: context.loc.topRated,
// ),
// AppListTile(
// onPressed: () {},
// isSelected: false,
// svgPath: AppIcons.icClock,
// title: context.loc.fast,
// ),
],
);
}
}

View File

@@ -9,8 +9,6 @@ class WHomeHeader extends StatelessWidget {
Widget build(BuildContext context) {
return BlocBuilder<HomeBloc, HomeState>(
builder: (context, state) {
return DecoratedBox(
decoration: BoxDecoration(color: AppColors.cFFFFFF),
child: Column(
@@ -37,7 +35,12 @@ class WHomeHeader extends StatelessWidget {
Align(
alignment: AlignmentGeometry.topRight,
child: IconButton(
onPressed: () {},
onPressed: () {
context.push(
Routes.filters,
extra: context.read<HomeBloc>(),
);
},
icon: SvgPicture.asset(
AppIcons.icFilter,
height: 36,

View File

@@ -66,6 +66,7 @@ class _WRatingBottomSheetState extends State<WRatingBottomSheet> {
15.verticalSpace,
Wrap(
spacing: 10,
runSpacing: 15,
children: List.generate(value.length, (index) {
return WRatingButton(
onTap: () {