feat: filters added to home page
This commit is contained in:
@@ -9,3 +9,6 @@ export 'presentation/pages/home_page/widgets/w_offers_carouseL_slider.dart';
|
||||
export 'presentation/pages/home_page/widgets/w_popular_near_you.dart';
|
||||
export 'presentation/pages/home_page/widgets/w_todays_offers.dart';
|
||||
export 'package:food_delivery_client/feature/home/presentation/pages/home_page/widgets/pick_it_for_free.dart';
|
||||
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';
|
||||
|
||||
@@ -5,13 +5,33 @@ part 'home_event.dart';
|
||||
part 'home_state.dart';
|
||||
|
||||
part 'home_bloc.freezed.dart';
|
||||
|
||||
@injectable
|
||||
class HomeBloc extends Bloc<HomeEvent, HomeState> {
|
||||
HomeBloc() : super(const HomeState()) {
|
||||
on<_Changed>(_onChanged);
|
||||
on<_Filtered>(_onFiltered);
|
||||
on<_Rated>(_onRated);
|
||||
}
|
||||
|
||||
void _onChanged(_Changed event, Emitter<HomeState> emit) {
|
||||
emit(state.copyWith(currentIndex: event.index));
|
||||
}
|
||||
|
||||
void _onFiltered(_Filtered event, Emitter<HomeState> emit) {
|
||||
final oldFilters = List.from(state.filters);
|
||||
if (oldFilters.contains(event.filter)) {
|
||||
final newFilters = oldFilters..remove(event.filter);
|
||||
emit(state.copyWith(filters: newFilters));
|
||||
} else {
|
||||
final newFilters = oldFilters..add(event.filter);
|
||||
emit(state.copyWith(filters: newFilters));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _onRated(_Rated event, Emitter<HomeState> emit){
|
||||
emit(state.copyWith(rating: event.filter));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +55,14 @@ extension HomeEventPatterns on HomeEvent {
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>({TResult Function( _Started value)? started,TResult Function( _Changed value)? changed,required TResult orElse(),}){
|
||||
@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(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _Started() when started != null:
|
||||
return started(_that);case _Changed() when changed != null:
|
||||
return changed(_that);case _:
|
||||
return changed(_that);case _Filtered() when filtered != null:
|
||||
return filtered(_that);case _Rated() when rated != null:
|
||||
return rated(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -78,12 +80,14 @@ return changed(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>({required TResult Function( _Started value) started,required TResult Function( _Changed value) changed,}){
|
||||
@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,}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _Started():
|
||||
return started(_that);case _Changed():
|
||||
return changed(_that);case _:
|
||||
return changed(_that);case _Filtered():
|
||||
return filtered(_that);case _Rated():
|
||||
return rated(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -100,12 +104,14 @@ return changed(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>({TResult? Function( _Started value)? started,TResult? Function( _Changed value)? changed,}){
|
||||
@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,}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _Started() when started != null:
|
||||
return started(_that);case _Changed() when changed != null:
|
||||
return changed(_that);case _:
|
||||
return changed(_that);case _Filtered() when filtered != null:
|
||||
return filtered(_that);case _Rated() when rated != null:
|
||||
return rated(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -122,11 +128,13 @@ return changed(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>({TResult Function()? started,TResult Function( int index)? changed,required TResult orElse(),}) {final _that = this;
|
||||
@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;
|
||||
switch (_that) {
|
||||
case _Started() when started != null:
|
||||
return started();case _Changed() when changed != null:
|
||||
return changed(_that.index);case _:
|
||||
return changed(_that.index);case _Filtered() when filtered != null:
|
||||
return filtered(_that.filter);case _Rated() when rated != null:
|
||||
return rated(_that.filter);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -144,11 +152,13 @@ return changed(_that.index);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>({required TResult Function() started,required TResult Function( int index) changed,}) {final _that = this;
|
||||
@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;
|
||||
switch (_that) {
|
||||
case _Started():
|
||||
return started();case _Changed():
|
||||
return changed(_that.index);case _:
|
||||
return changed(_that.index);case _Filtered():
|
||||
return filtered(_that.filter);case _Rated():
|
||||
return rated(_that.filter);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -165,11 +175,13 @@ return changed(_that.index);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>({TResult? Function()? started,TResult? Function( int index)? changed,}) {final _that = this;
|
||||
@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;
|
||||
switch (_that) {
|
||||
case _Started() when started != null:
|
||||
return started();case _Changed() when changed != null:
|
||||
return changed(_that.index);case _:
|
||||
return changed(_that.index);case _Filtered() when filtered != null:
|
||||
return filtered(_that.filter);case _Rated() when rated != null:
|
||||
return rated(_that.filter);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -273,12 +285,150 @@ as int,
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _Filtered implements HomeEvent {
|
||||
const _Filtered(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')
|
||||
_$FilteredCopyWith<_Filtered> get copyWith => __$FilteredCopyWithImpl<_Filtered>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Filtered&&(identical(other.filter, filter) || other.filter == filter));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,filter);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HomeEvent.filtered(filter: $filter)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$FilteredCopyWith<$Res> implements $HomeEventCopyWith<$Res> {
|
||||
factory _$FilteredCopyWith(_Filtered value, $Res Function(_Filtered) _then) = __$FilteredCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String filter
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$FilteredCopyWithImpl<$Res>
|
||||
implements _$FilteredCopyWith<$Res> {
|
||||
__$FilteredCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _Filtered _self;
|
||||
final $Res Function(_Filtered) _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(_Filtered(
|
||||
null == filter ? _self.filter : filter // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _Rated implements HomeEvent {
|
||||
const _Rated(final List<String> filter): _filter = filter;
|
||||
|
||||
|
||||
final List<String> _filter;
|
||||
List<String> get filter {
|
||||
if (_filter is EqualUnmodifiableListView) return _filter;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_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')
|
||||
_$RatedCopyWith<_Rated> get copyWith => __$RatedCopyWithImpl<_Rated>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _Rated&&const DeepCollectionEquality().equals(other._filter, _filter));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_filter));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HomeEvent.rated(filter: $filter)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$RatedCopyWith<$Res> implements $HomeEventCopyWith<$Res> {
|
||||
factory _$RatedCopyWith(_Rated value, $Res Function(_Rated) _then) = __$RatedCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
List<String> filter
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$RatedCopyWithImpl<$Res>
|
||||
implements _$RatedCopyWith<$Res> {
|
||||
__$RatedCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _Rated _self;
|
||||
final $Res Function(_Rated) _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(_Rated(
|
||||
null == filter ? _self._filter : filter // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$HomeState {
|
||||
|
||||
int get currentIndex;
|
||||
int get currentIndex; 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)
|
||||
@@ -289,16 +439,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));
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,currentIndex);
|
||||
int get hashCode => Object.hash(runtimeType,currentIndex,const DeepCollectionEquality().hash(filters),const DeepCollectionEquality().hash(rating));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HomeState(currentIndex: $currentIndex)';
|
||||
return 'HomeState(currentIndex: $currentIndex, filters: $filters, rating: $rating)';
|
||||
}
|
||||
|
||||
|
||||
@@ -309,7 +459,7 @@ abstract mixin class $HomeStateCopyWith<$Res> {
|
||||
factory $HomeStateCopyWith(HomeState value, $Res Function(HomeState) _then) = _$HomeStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
int currentIndex
|
||||
int currentIndex, List filters, List<String> rating
|
||||
});
|
||||
|
||||
|
||||
@@ -326,10 +476,12 @@ 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,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? currentIndex = 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,
|
||||
as int,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>,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -414,10 +566,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int currentIndex)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int currentIndex, List filters, List<String> rating)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _HomeState() when $default != null:
|
||||
return $default(_that.currentIndex);case _:
|
||||
return $default(_that.currentIndex,_that.filters,_that.rating);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -435,10 +587,10 @@ return $default(_that.currentIndex);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int currentIndex) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int currentIndex, List filters, List<String> rating) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _HomeState():
|
||||
return $default(_that.currentIndex);case _:
|
||||
return $default(_that.currentIndex,_that.filters,_that.rating);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -455,10 +607,10 @@ return $default(_that.currentIndex);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int currentIndex)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int currentIndex, List filters, List<String> rating)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _HomeState() when $default != null:
|
||||
return $default(_that.currentIndex);case _:
|
||||
return $default(_that.currentIndex,_that.filters,_that.rating);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -470,10 +622,24 @@ return $default(_that.currentIndex);case _:
|
||||
|
||||
|
||||
class _HomeState implements HomeState {
|
||||
const _HomeState({this.currentIndex = 0});
|
||||
const _HomeState({this.currentIndex = 0, final List filters = const [], final List<String> rating = const []}): _filters = filters,_rating = rating;
|
||||
|
||||
|
||||
@override@JsonKey() final int currentIndex;
|
||||
final List _filters;
|
||||
@override@JsonKey() List get filters {
|
||||
if (_filters is EqualUnmodifiableListView) return _filters;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_filters);
|
||||
}
|
||||
|
||||
final List<String> _rating;
|
||||
@override@JsonKey() List<String> get rating {
|
||||
if (_rating is EqualUnmodifiableListView) return _rating;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_rating);
|
||||
}
|
||||
|
||||
|
||||
/// Create a copy of HomeState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -485,16 +651,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));
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,currentIndex);
|
||||
int get hashCode => Object.hash(runtimeType,currentIndex,const DeepCollectionEquality().hash(_filters),const DeepCollectionEquality().hash(_rating));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HomeState(currentIndex: $currentIndex)';
|
||||
return 'HomeState(currentIndex: $currentIndex, filters: $filters, rating: $rating)';
|
||||
}
|
||||
|
||||
|
||||
@@ -505,7 +671,7 @@ abstract mixin class _$HomeStateCopyWith<$Res> implements $HomeStateCopyWith<$Re
|
||||
factory _$HomeStateCopyWith(_HomeState value, $Res Function(_HomeState) _then) = __$HomeStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
int currentIndex
|
||||
int currentIndex, List filters, List<String> rating
|
||||
});
|
||||
|
||||
|
||||
@@ -522,10 +688,12 @@ 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,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? currentIndex = null,Object? filters = null,Object? rating = null,}) {
|
||||
return _then(_HomeState(
|
||||
currentIndex: null == currentIndex ? _self.currentIndex : currentIndex // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
as int,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>,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -4,5 +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.filtered(String filter) = _Filtered;
|
||||
const factory HomeEvent.rated(List<String> filter) = _Rated;
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ part of 'home_bloc.dart';
|
||||
@freezed
|
||||
abstract class HomeState with _$HomeState {
|
||||
const factory HomeState({
|
||||
@Default(0) int currentIndex
|
||||
}) = _HomeState;
|
||||
@Default(0) int currentIndex,
|
||||
@Default([]) List filters,
|
||||
@Default([]) List<String> rating
|
||||
|
||||
}) = _HomeState;
|
||||
}
|
||||
|
||||
@@ -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