Skip to content

Commit

Permalink
Add release event list screen
Browse files Browse the repository at this point in the history
  • Loading branch information
up2code committed May 9, 2024
1 parent b055fdf commit 5b39677
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ class HomeScreen extends StatelessWidget {
ShortcutMenuButton(
title: 'Events',
iconData: Icons.event,
onPressed: () {},
onPressed: () {
context.goReleaseEventList();
},
)
],
),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:vocadb_app/src/features/releaseEvents/domain/release_events_list_params.dart';
import 'package:vocadb_app/src/features/settings/data/user_settings_repository.dart';

class ReleaseEventsListParamsState extends StateNotifier<ReleaseEventsListParams> {
ReleaseEventsListParamsState({String lang = 'Default'})
: super(ReleaseEventsListParams(lang: lang));
void updateQuery(String value) => state = state.copyWith(query: value);
void updateSort(String value) => state = state.copyWith(sort: value);
void clearQuery() => state = state.copyWith(query: null);
}

final releaseEventsListParamsStateProvider = StateNotifierProvider.autoDispose<
ReleaseEventsListParamsState, ReleaseEventsListParams>((ref) {
final preferredLang = ref.watch(userSettingsRepositoryProvider
.select((value) => value.currentPreferredLang));
return ReleaseEventsListParamsState(lang: preferredLang);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:vocadb_app/src/common_widgets/async_value_widget.dart';
import 'package:vocadb_app/src/common_widgets/search_appbar.dart';
import 'package:vocadb_app/src/features/artists/data/artist_repository.dart';
import 'package:vocadb_app/src/features/artists/domain/artist.dart';
import 'package:vocadb_app/src/features/artists/presentation/artists_list/artist_list_view.dart';
import 'package:vocadb_app/src/features/artists/presentation/artists_list_screen/artists_list_params_state.dart';
import 'package:vocadb_app/src/features/releaseEvents/data/release_event_repository.dart';
import 'package:vocadb_app/src/features/releaseEvents/domain/release_event.dart';
import 'package:vocadb_app/src/features/releaseEvents/presentation/release_events_list/release_events_list_view.dart';
import 'package:vocadb_app/src/features/releaseEvents/presentation/release_events_list_screen/release_events_list_params_state.dart';
import 'package:vocadb_app/src/routing/app_route_context.dart';

class ReleaseEventsListScreen extends ConsumerWidget {
const ReleaseEventsListScreen({super.key, this.onSelectEvent});

static const filterKey = Key('icon-filter-key');

final Function(ReleaseEvent)? onSelectEvent;

@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: SearchAppBar(
titleText: 'Events',
onSubmitted: (value) {
ref.read(releaseEventsListParamsStateProvider.notifier).updateQuery(value);
},
onCleared: () {
ref.read(releaseEventsListParamsStateProvider.notifier).clearQuery();
},
),
body: Consumer(builder: ((context, ref, child) {
final value = ref.watch(releaseEventsListProvider);
return AsyncValueWidget(
value: value,
data: (data) {
return ReleaseEventsListView(
events: data,
onSelect: (event) => onSelectEvent?.call(event),
);
});
})),
);
}
}

// State
final releaseEventsListProvider = FutureProvider.autoDispose<List<ReleaseEvent>>((ref) {
final params = ref.watch(releaseEventsListParamsStateProvider);
final releaseEventRepository = ref.watch(releaseEventRepositoryProvider);
return releaseEventRepository.fetchReleaseEventsList(params: params);
});
4 changes: 4 additions & 0 deletions lib/src/routing/app_route_context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ extension AppRouteContext on BuildContext {
goNamed(AppRoute.releaseEventDetail.name, pathParameters: { 'id': releaseEvent.id.toString() });
}

Future<void> goReleaseEventList() async {
goNamed(AppRoute.releaseEventList.name);
}

Future<void> goArtistSearchScreen() async {
goNamed(AppRoute.artistsList.name);

Expand Down
15 changes: 15 additions & 0 deletions lib/src/routing/app_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:vocadb_app/src/features/albums/domain/album.dart';
import 'package:vocadb_app/src/features/albums/presentation/album_detail_screen/album_detail_screen.dart';
import 'package:vocadb_app/src/features/albums/presentation/albums_list/albums_list_filter_screen.dart';
import 'package:vocadb_app/src/features/albums/presentation/albums_list/albums_list_screen.dart';
import 'package:vocadb_app/src/features/releaseEvents/presentation/release_events_list_screen/release_events_list_screen.dart';
import 'package:vocadb_app/src/features/songs/presentation/songs_list_screen/songs_list_filter_screen.dart';
import 'package:vocadb_app/src/features/songs/presentation/songs_list_screen/songs_list_screen.dart';
import 'package:vocadb_app/src/features/users/presentation/user_albums_screen/user_albums_filter_screen.dart';
Expand Down Expand Up @@ -48,6 +49,7 @@ enum AppRoute {
artistsList,
artistsListFilter,
tagDetail,
releaseEventList,
releaseEventDetail,
entriesSearch,
entriesFilter,
Expand Down Expand Up @@ -191,6 +193,15 @@ final goRouterProvider = Provider.autoDispose<GoRouter>(
),

//// Release events
GoRoute(
path: 'E',
name: AppRoute.releaseEventList.name,
builder: (context, state) {
return ReleaseEventsListScreen(onSelectEvent: (event) {
context.goReleaseEventDetail(event);
});
},
routes: [
GoRoute(
path: 'E/:id',
name: AppRoute.releaseEventDetail.name,
Expand All @@ -199,6 +210,10 @@ final goRouterProvider = Provider.autoDispose<GoRouter>(
return ReleaseEventDetailScreen(releaseEventId: releaseEventId);
},
),
],
),



//// Personal
GoRoute(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:vocadb_app/src/features/releaseEvents/data/release_event_repository.dart';
import 'package:vocadb_app/src/features/releaseEvents/presentation/release_event_tile/release_event_tile.dart';
import 'package:vocadb_app/src/features/releaseEvents/presentation/release_events_list_screen/release_events_list_screen.dart';
import 'package:vocadb_app/src/features/settings/data/user_settings_repository.dart';

class ReleaseEventsListScreenRobot {
final WidgetTester tester;

ReleaseEventsListScreenRobot(this.tester);

Future<void> pumpReleaseEventsListScreen(
{ReleaseEventRepository? releaseEventRepository}) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
if (releaseEventRepository != null)
releaseEventRepositoryProvider.overrideWithValue(releaseEventRepository),
userSettingsRepositoryProvider
.overrideWithValue(UserSettingsRepository())
],
child: const MaterialApp(
home: ReleaseEventsListScreen(),
),
),
);

await tester.pump();
await tester.pump();
await tester.pump();
}

Future<void> expectReleaseEventsDisplayCountAtLeast(int count) async {
final finder = find.byType(ReleaseEventTile);
expect(finder, findsAtLeastNWidgets(count));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:vocadb_app/src/features/releaseEvents/data/constants/fake_release_events_list.dart';
import 'package:vocadb_app/src/features/releaseEvents/domain/release_events_list_params.dart';

import '../../../../mocks.dart';
import 'release_events_list_screen_robot.dart';

void main() {
testWidgets('Release events list screen ...', (tester) async {
registerFallbackValue(FakeReleaseEventsListParams());

final r = ReleaseEventsListScreenRobot(tester);
final releaseEventRepository = MockReleaseEventRepository();

when(() => releaseEventRepository.fetchReleaseEventsList(
params: any(named: 'params', that: isNotNull),
)).thenAnswer((_) => Future.value(kFakeReleaseEventsList));

await r.pumpReleaseEventsListScreen(releaseEventRepository: releaseEventRepository);

await r.expectReleaseEventsDisplayCountAtLeast(3);

expect(
verify(() =>
releaseEventRepository.fetchReleaseEventsList(params: captureAny(named: 'params')))
.captured,
[
const ReleaseEventsListParams(),
]);
});
}
3 changes: 3 additions & 0 deletions test/src/mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:vocadb_app/src/features/artists/domain/artists_list_params.dart'
import 'package:vocadb_app/src/features/authentication/data/auth_repository.dart';
import 'package:vocadb_app/src/features/entries/data/entry_repository.dart';
import 'package:vocadb_app/src/features/releaseEvents/data/release_event_repository.dart';
import 'package:vocadb_app/src/features/releaseEvents/domain/release_events_list_params.dart';
import 'package:vocadb_app/src/features/settings/data/user_settings_repository.dart';
import 'package:vocadb_app/src/features/songs/data/song_repository.dart';
import 'package:vocadb_app/src/features/songs/domain/songs_list_params.dart';
Expand Down Expand Up @@ -38,6 +39,8 @@ class RatedSongsListParamsFake extends Fake implements RatedSongsListParams {}

class FakeArtistsListParams extends Fake implements ArtistsListParams {}

class FakeReleaseEventsListParams extends Fake implements ReleaseEventsListParams {}

class FakeAlbumsListParams extends Fake implements AlbumsListParams {}

class FakeSongsListParams extends Fake implements SongsListParams {}
Expand Down

0 comments on commit 5b39677

Please sign in to comment.