Skip to content

Commit 3afa3dc

Browse files
committed
feat: implement contest filter bottom sheet
1 parent 1648c8c commit 3afa3dc

11 files changed

Lines changed: 368 additions & 6 deletions

File tree

lib/data/constants/assets.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ class AppAssets {
1515
static const String bell = '$_iconsRoot/bell.svg';
1616
static const String selectedBell = '$_iconsRoot/selected_bell.svg';
1717
static const String clock = '$_iconsRoot/clock.svg';
18+
static const String trueRadioButton = '$_iconsRoot/true_radio_button.svg';
19+
static const String falseRadioButton = '$_iconsRoot/false_radio_button.svg';
1820

1921
// Images
2022
static const String circle1 = '$_imagesRoot/circle1.svg';

lib/data/constants/colors.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class AppColors {
99
static const Color grey5 = Color(0x3D000000);
1010
static const Color grey6 = Color(0xFF919191);
1111
static const Color grey7 = Color(0xFFF3F4F7);
12+
static const Color grey8 = Color(0xFFC8C8C8);
1213
static const Color transparent = Colors.transparent;
1314

1415
static const Color primary = Color(0xFF3366FF);

lib/data/services/local/storage_service.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:convert';
22

33
import 'package:hive_flutter/hive_flutter.dart';
44

5+
import '../../../domain/models/contest_filter.dart';
56
import '../../../domain/models/user.dart';
67
import '../../constants/strings.dart';
78

@@ -66,4 +67,16 @@ class StorageService {
6667
_set<String?>(AppStrings.userKey, null);
6768
}
6869
}
70+
71+
static ContestFilter? get filter {
72+
try {
73+
return ContestFilter.fromJson(
74+
json.decode(_get<String>(AppStrings.filterKey)!));
75+
} on Exception catch (_) {
76+
return null;
77+
}
78+
}
79+
80+
static set filter(ContestFilter? _filter) =>
81+
_set(AppStrings.filterKey, json.encode(_filter!.toJson()));
6982
}

lib/presentation/contests/bloc/contests_bloc.dart

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:developer';
2+
13
import 'package:equatable/equatable.dart';
24
import 'package:flutter_bloc/flutter_bloc.dart';
35
import 'package:freezed_annotation/freezed_annotation.dart';
@@ -16,6 +18,7 @@ class ContestsBloc extends Bloc<ContestsEvent, ContestsState> {
1618
ContestsBloc() : super(const ContestsState()) {
1719
on<FetchContests>(_fetchContests);
1820
on<UpdateFilter>(_updateFilter);
21+
on<FilterButton>(_filterButton);
1922
}
2023

2124
void _fetchContests(FetchContests event, Emitter<ContestsState> emit) async {
@@ -24,10 +27,28 @@ class ContestsBloc extends Bloc<ContestsEvent, ContestsState> {
2427
_upcoming = [...?contest?.upcoming];
2528
applyFilter();
2629
final contests = [..._filteredUpcoming, ..._filteredOngoing];
27-
emit(state.copyWith(contests: contests, isLoading: false));
30+
emit(state.copyWith(
31+
contests: contests,
32+
isLoading: false,
33+
filter: _filter,
34+
));
35+
}
36+
37+
void _filterButton(FilterButton event, Emitter<ContestsState> emit) {
38+
_updatedfilter = _filter;
39+
40+
emit(state.copyWith(duration: _updatedfilter?.duration));
2841
}
2942

30-
void _updateFilter(UpdateFilter event, Emitter<ContestsState> emit) {}
43+
void _updateFilter(UpdateFilter event, Emitter<ContestsState> emit) {
44+
if (event.updatedFilter != null) _updatedfilter = event.updatedFilter;
45+
emit(
46+
state.copyWith(
47+
duration: event.duration ?? _updatedfilter?.duration,
48+
filter: event.updatedFilter ?? _updatedfilter,
49+
),
50+
);
51+
}
3152

3253
void applyFilter() {
3354
_filteredOngoing = [];
@@ -53,7 +74,7 @@ class ContestsBloc extends Bloc<ContestsEvent, ContestsState> {
5374
}
5475
}
5576

56-
ContestFilter? _filter;
77+
ContestFilter? _filter, _updatedfilter;
5778
List<Ongoing> _ongoing = [], _filteredOngoing = [];
5879
List<Upcoming> _upcoming = [], _filteredUpcoming = [];
5980

@@ -70,8 +91,14 @@ class ContestsBloc extends Bloc<ContestsEvent, ContestsState> {
7091
}
7192

7293
_filter = StorageService.filter;
94+
_updatedfilter = _filter;
7395
add(const FetchContests());
7496
}
97+
98+
void saveFilter() {
99+
log('save filter is called');
100+
_filter = _updatedfilter;
101+
}
75102
}
76103

77104
extension on ContestFilter {

lib/presentation/contests/bloc/contests_event.dart

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,21 @@ class FetchContests extends ContestsEvent {
1414
List<Object?> get props => [];
1515
}
1616

17-
class UpdateFilter extends ContestsEvent {
18-
const UpdateFilter();
17+
class FilterButton extends ContestsEvent {
18+
const FilterButton();
1919

2020
@override
2121
List<Object?> get props => [];
2222
}
23+
24+
class UpdateFilter extends ContestsEvent {
25+
const UpdateFilter({
26+
this.duration,
27+
this.updatedFilter,
28+
});
29+
final int? duration;
30+
final ContestFilter? updatedFilter;
31+
32+
@override
33+
List<Object?> get props => [updatedFilter, duration];
34+
}

lib/presentation/contests/bloc/contests_state.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ class ContestsState with _$ContestsState {
55
const factory ContestsState({
66
@Default(true) bool isLoading,
77
@Default([]) List contests,
8+
ContestFilter? filter,
9+
int? duration,
810
}) = _ContestsState;
911

1012
const ContestsState._();

lib/presentation/contests/widgets/contest_header.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import 'package:flutter_svg/flutter_svg.dart';
55
import '../../../data/constants/assets.dart';
66
import '../../../data/constants/colors.dart';
77
import '../bloc/contests_bloc.dart';
8+
import 'filter_sheet.dart';
89

910
class ContestHeader extends StatelessWidget {
1011
const ContestHeader({Key? key}) : super(key: key);
@@ -25,7 +26,14 @@ class ContestHeader extends StatelessWidget {
2526
actions: [
2627
IconButton(
2728
onPressed: () {
28-
context.read<ContestsBloc>().add(const UpdateFilter());
29+
final bloc = context.read<ContestsBloc>()
30+
..add(const FilterButton());
31+
showModalBottomSheet(
32+
context: context,
33+
builder: (_) {
34+
return FilterSheet(bloc: bloc);
35+
},
36+
);
2937
},
3038
icon: SvgPicture.asset(AppAssets.filter),
3139
),

0 commit comments

Comments
 (0)