From 2ca4e65a08954dff455ad3cc16281308978435a3 Mon Sep 17 00:00:00 2001 From: Sebastine Odeh Date: Sat, 12 Oct 2024 17:12:34 +0100 Subject: [PATCH 1/8] integration --- packages/cave/lib/cave.dart | 2 + packages/cave/pubspec.yaml | 2 + packages/conferenceapp/ios/Podfile.lock | 13 + .../application/agenda/view_model.dart | 23 +- .../application/speakers/view_model.dart | 15 ++ .../application/sponsors/view_model.dart | 6 + .../presentation/screens/dashboard.dart | 11 +- .../home/presentation/screens/home.dart | 171 ++++++++++--- .../widgets/agenda_talk_tile.dart | 33 ++- .../presentation/widgets/schedule_tile.dart | 20 +- .../presentation/widgets/sponsor_tile.dart | 15 +- .../more/presentation/screens/home.dart | 17 +- .../more/presentation/screens/my_qr_code.dart | 12 +- .../more/presentation/screens/profile.dart | 46 ++-- .../widgets/user_header_tiles.dart | 99 ++++---- .../reserve/presentation/screens/home.dart | 14 +- .../schedule/presentation/screens/home.dart | 84 +++++-- .../widgets/conference_schedule_tile.dart | 61 +++-- .../speakers/presentation/screens/home.dart | 132 ++++++++-- .../presentation/screens/speaker_details.dart | 73 +++--- .../presentation/widgets/speaker_tile.dart | 25 +- .../lib/src/routing/extra_codec.dart | 49 ++++ .../conferenceapp/lib/src/routing/router.dart | 7 +- .../lib/src/shared/extensions.dart | 10 + .../conferenceapp/lib/src/shared/shared.dart | 1 + .../conferenceapp/lib/src/shared/utility.dart | 11 + .../lib/src/shared/widgets/agenda_header.dart | 5 +- packages/conferenceapp/pubspec.lock | 228 +++++++++++++++++- packages/conferenceapp/pubspec.yaml | 7 +- 29 files changed, 945 insertions(+), 247 deletions(-) create mode 100644 packages/conferenceapp/lib/src/routing/extra_codec.dart create mode 100644 packages/conferenceapp/lib/src/shared/utility.dart diff --git a/packages/cave/lib/cave.dart b/packages/cave/lib/cave.dart index 47baa6b..f815150 100644 --- a/packages/cave/lib/cave.dart +++ b/packages/cave/lib/cave.dart @@ -12,3 +12,5 @@ export 'package:flutter_secure_storage/flutter_secure_storage.dart'; export 'utils/utils.dart'; export 'package:shared_preferences/shared_preferences.dart'; export 'package:shimmer/shimmer.dart'; +export 'package:cached_network_image/cached_network_image.dart'; +export 'package:qr_flutter/qr_flutter.dart'; diff --git a/packages/cave/pubspec.yaml b/packages/cave/pubspec.yaml index f757b5e..5179f22 100644 --- a/packages/cave/pubspec.yaml +++ b/packages/cave/pubspec.yaml @@ -21,6 +21,8 @@ dependencies: flutter_secure_storage: ^9.2.2 shared_preferences: ^2.3.2 shimmer: ^3.0.0 + cached_network_image: ^3.4.1 + qr_flutter: ^4.1.0 dev_dependencies: flutter_lints: ^5.0.0 diff --git a/packages/conferenceapp/ios/Podfile.lock b/packages/conferenceapp/ios/Podfile.lock index fa6322b..60f5d13 100644 --- a/packages/conferenceapp/ios/Podfile.lock +++ b/packages/conferenceapp/ios/Podfile.lock @@ -76,6 +76,11 @@ PODS: - shared_preferences_foundation (0.0.1): - Flutter - FlutterMacOS + - sqflite_darwin (0.0.4): + - Flutter + - FlutterMacOS + - url_launcher_ios (0.0.1): + - Flutter DEPENDENCIES: - firebase_core (from `.symlinks/plugins/firebase_core/ios`) @@ -85,6 +90,8 @@ DEPENDENCIES: - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) + - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) SPEC REPOS: trunk: @@ -119,6 +126,10 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/path_provider_foundation/darwin" shared_preferences_foundation: :path: ".symlinks/plugins/shared_preferences_foundation/darwin" + sqflite_darwin: + :path: ".symlinks/plugins/sqflite_darwin/darwin" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" SPEC CHECKSUMS: Firebase: cec914dab6fd7b1bd8ab56ea07ce4e03dd251c2d @@ -143,6 +154,8 @@ SPEC CHECKSUMS: path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 + sqflite_darwin: a553b1fd6fe66f53bbb0fe5b4f5bab93f08d7a13 + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe PODFILE CHECKSUM: 1959d098c91d8a792531a723c4a9d7e9f6a01e38 diff --git a/packages/conferenceapp/lib/src/features/dashboard/application/agenda/view_model.dart b/packages/conferenceapp/lib/src/features/dashboard/application/agenda/view_model.dart index 42e129f..e8e5d41 100644 --- a/packages/conferenceapp/lib/src/features/dashboard/application/agenda/view_model.dart +++ b/packages/conferenceapp/lib/src/features/dashboard/application/agenda/view_model.dart @@ -11,6 +11,17 @@ final agendasViewModelNotifier = () => AgendaViewModel(), ); +final dayOneSessionsProvider = Provider.autoDispose>((ref) { + return ref.watch(agendasViewModelNotifier.select((vm) => vm.agendas + .where((agenda) => agenda.start?.day == 15) + .fold([], (previous, next) => [...previous, ...next.sessions.sessions]))); +}, dependencies: [agendasViewModelNotifier]); +final dayTwoSessionsProvider = Provider.autoDispose>((ref) { + return ref.watch(agendasViewModelNotifier.select((vm) => vm.agendas + .where((agenda) => agenda.start?.day == 16) + .fold([], (previous, next) => [...previous, ...next.sessions.sessions]))); +}, dependencies: [agendasViewModelNotifier]); + final class AgendaViewModel extends AutoDisposeNotifier { late DashboardApiService _apiService; @@ -27,7 +38,17 @@ final class AgendaViewModel extends AutoDisposeNotifier { state = model.emit( result.fold( - (left) => state.copyWith(uiState: UiState.error, error: left), + (left) { + if (left is WithCachedDataException) { + return state.copyWith( + uiState: UiState.error, + error: left, + agendas: (left.result as AgendasDto).agendas, + ); + } + + return state.copyWith(uiState: UiState.error, error: left); + }, (right) => state.copyWith(uiState: UiState.success, agendas: right.agendas), ), diff --git a/packages/conferenceapp/lib/src/features/dashboard/application/speakers/view_model.dart b/packages/conferenceapp/lib/src/features/dashboard/application/speakers/view_model.dart index 4fab9e4..047d405 100644 --- a/packages/conferenceapp/lib/src/features/dashboard/application/speakers/view_model.dart +++ b/packages/conferenceapp/lib/src/features/dashboard/application/speakers/view_model.dart @@ -11,6 +11,21 @@ final speakersViewModelNotifier = () => SpeakersViewModel(), ); +final dayOneSpeakersProvider = Provider.autoDispose>((ref) { + return ref.watch(speakersViewModelNotifier.select((vm) => vm.speakers + .where((speaker) => speaker.sessions + .where((session) => session.startTime!.day == 15) + .isNotEmpty) + .toList())); +}, dependencies: [speakersViewModelNotifier]); +final dayTwoSpeakersProvider = Provider.autoDispose>((ref) { + return ref.watch(speakersViewModelNotifier.select((vm) => vm.speakers + .where((speaker) => speaker.sessions + .where((session) => session.startTime!.day == 16) + .isNotEmpty) + .toList())); +}, dependencies: [speakersViewModelNotifier]); + final class SpeakersViewModel extends AutoDisposeNotifier { late DashboardApiService _apiService; diff --git a/packages/conferenceapp/lib/src/features/dashboard/application/sponsors/view_model.dart b/packages/conferenceapp/lib/src/features/dashboard/application/sponsors/view_model.dart index 1fadd73..e8a64df 100644 --- a/packages/conferenceapp/lib/src/features/dashboard/application/sponsors/view_model.dart +++ b/packages/conferenceapp/lib/src/features/dashboard/application/sponsors/view_model.dart @@ -11,6 +11,12 @@ final sponsorsViewModelNotifier = () => SponsorsViewModel(), ); +final sponsorsProvider = Provider.autoDispose>((ref) { + return ref.watch(sponsorsViewModelNotifier.select((vm) => vm.sponsorCategories + .fold([], + (previous, next) => [...previous, ...next.sponsors]))); +}); + final class SponsorsViewModel extends AutoDisposeNotifier { late DashboardApiService _apiService; diff --git a/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart b/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart index d34dd2d..9c9a96d 100644 --- a/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart +++ b/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart @@ -2,7 +2,6 @@ import 'package:cave/cave.dart'; import 'package:devfest24/src/features/dashboard/application/application.dart'; import 'package:devfest24/src/features/home/presentation/presentation.dart'; import 'package:devfest24/src/features/more/presentation/presentation.dart'; -import 'package:devfest24/src/features/reserve/presentation/presentation.dart'; import 'package:devfest24/src/features/schedule/presentation/presentation.dart'; import 'package:devfest24/src/features/speakers/presentation/presentation.dart'; import 'package:flutter/material.dart'; @@ -15,7 +14,10 @@ class DashboardScreen extends StatelessWidget { @override Widget build(BuildContext context) { - return const DefaultTabController(length: 5, child: _View()); + return DefaultTabController( + length: _ViewState._tabs.length, + child: _View(), + ); } } @@ -32,7 +34,6 @@ class _ViewState extends ConsumerState<_View> { KeepAliveWidget(child: HomeScreen()), KeepAliveWidget(child: ScheduleHomeScreen()), KeepAliveWidget(child: SpeakersHomeScreen()), - KeepAliveWidget(child: ReserveHomeScreen()), KeepAliveWidget(child: MoreHomeScreen()), ]; @@ -94,10 +95,6 @@ class _ViewState extends ConsumerState<_View> { label: 'Speakers', icon: Icon(IconsaxOutline.microphone), ), - DevfestBottomNavItem( - label: 'Reserve', - icon: Icon(IconsaxOutline.ticket), - ), DevfestBottomNavItem( label: 'More', icon: Icon(IconsaxOutline.more_square), diff --git a/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart index e787c1c..8b0851a 100644 --- a/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart @@ -1,11 +1,13 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; -import 'package:devfest24/src/features/dashboard/application/user/view_model.dart'; +import 'package:devfest24/src/features/dashboard/application/application.dart'; +import 'package:devfest24/src/features/dashboard/model/model.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../widgets/widgets.dart'; +import 'package:collection/collection.dart'; class HomeScreen extends ConsumerStatefulWidget { const HomeScreen({super.key}); @@ -15,6 +17,8 @@ class HomeScreen extends ConsumerStatefulWidget { } class _HomeScreenState extends ConsumerState { + EventDay _day = EventDay.one; + @override Widget build(BuildContext context) { return Scaffold( @@ -29,7 +33,10 @@ class _HomeScreenState extends ConsumerState { ], ), actions: [ - const CheckInButton(), + CheckInButton( + isLoggedIn: ref.watch( + userViewModelNotifier.select((vm) => vm.user.id.isNotEmpty)), + ), Constants.horizontalMargin.horizontalSpace, ], ), @@ -37,13 +44,21 @@ class _HomeScreenState extends ConsumerState { padding: EdgeInsets.symmetric(horizontal: Constants.horizontalMargin.w), child: RefreshIndicator( onRefresh: () async { - await ref.read(userViewModelNotifier.notifier).fetchUserProfile(); + await Future.wait([ + ref + .read(userViewModelNotifier.notifier) + .fetchUserProfile(refresh: true), + ref + .read(sponsorsViewModelNotifier.notifier) + .fetchSponsors(refresh: true), + ]); }, child: CustomScrollView( slivers: [ - const SliverToBoxAdapter( + SliverToBoxAdapter( child: HeaderText( - title: Text('๐ŸŒค๏ธ Good morning, Aise'), + title: Text( + '๐ŸŒค๏ธ Good morning, ${ref.watch(userViewModelNotifier.select((value) => value.user.fullName.split(' ').first))}'), subtitle: Text( 'You start on the street, work till you are eleniyan.'), ), @@ -56,25 +71,45 @@ class _HomeScreenState extends ConsumerState { PinnedHeaderSliver( child: HomeAgendaHeader( title: const Text('๐Ÿ“† Schedule'), - onEventDayChanged: (day) {}, - onFilterSelected: () {}, + eventDay: _day, + onEventDayChanged: (day) { + setState(() { + _day = day; + }); + }, ), ), - SliverList.separated( - itemCount: 2, - itemBuilder: (context, index) => AgendaScheduleTile( - onTap: () {}, + [ + ProviderScope( + overrides: [ + _agendaSessionsProvider.overrideWithValue(ref + .watch(dayOneSessionsProvider) + .where((session) => session.categories.isEmpty) + .toList() + .safeSublist(2)), + ], + child: _AgendaSessions(), ), - separatorBuilder: (context, _) => - Constants.smallVerticalGutter.verticalSpace, - ), + ProviderScope( + overrides: [ + _agendaSessionsProvider.overrideWithValue(ref + .watch(dayTwoSessionsProvider) + .where((session) => session.categories.isEmpty) + .toList() + .safeSublist(2)), + ], + child: _AgendaSessions(), + ), + ].elementAt(_day.index), SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(top: Constants.verticalGutter) .h, child: InkWell( - onTap: () {}, + onTap: () { + DefaultTabController.of(context).index = 1; + }, child: Padding( padding: const EdgeInsets.symmetric( vertical: Constants.smallVerticalGutter) @@ -99,24 +134,39 @@ class _HomeScreenState extends ConsumerState { PinnedHeaderSliver( child: HomeAgendaHeader( title: const Text('๐ŸŽค Speakers'), - onEventDayChanged: (day) {}, + eventDay: _day, + onEventDayChanged: (day) { + setState(() { + _day = day; + }); + }, ), ), - SliverList.separated( - itemCount: 2, - itemBuilder: (context, index) => AgendaTalkTile( - onTap: () {}, + [ + ProviderScope( + overrides: [ + _speakersProvider.overrideWithValue( + ref.watch(dayOneSpeakersProvider).safeSublist(2)) + ], + child: _Speakers(), ), - separatorBuilder: (context, _) => - Constants.smallVerticalGutter.verticalSpace, - ), + ProviderScope( + overrides: [ + _speakersProvider.overrideWithValue( + ref.watch(dayTwoSpeakersProvider).safeSublist(2)) + ], + child: _Speakers(), + ), + ].elementAt(_day.index), SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(top: Constants.verticalGutter) .h, child: InkWell( - onTap: () {}, + onTap: () { + DefaultTabController.of(context).index = 2; + }, child: Padding( padding: const EdgeInsets.symmetric( vertical: Constants.smallVerticalGutter) @@ -124,7 +174,7 @@ class _HomeScreenState extends ConsumerState { child: const Center( child: IconText( Icons.arrow_forward, - 'View All Talks', + 'View All Speakers', alignment: IconTextAlignment.right, ), ), @@ -144,9 +194,12 @@ class _HomeScreenState extends ConsumerState { ), ), SliverList.separated( - itemCount: 4, + itemCount: ref.watch(sponsorsProvider).length, itemBuilder: (context, index) => ConferenceSponsorTile( - linkOnTap: () {}, + sponsor: ref.watch(sponsorsProvider)[index], + linkOnTap: () { + launchWebUrl(ref.read(sponsorsProvider)[index].website); + }, ), separatorBuilder: (context, _) => Constants.smallVerticalGutter.verticalSpace, @@ -162,3 +215,67 @@ class _HomeScreenState extends ConsumerState { ); } } + +final _agendaSessionsProvider = Provider.autoDispose>((ref) { + throw UnimplementedError(); +}); + +class _AgendaSessions extends ConsumerWidget { + const _AgendaSessions(); + + @override + Widget build(BuildContext context, ref) { + final sessions = ref.watch(_agendaSessionsProvider); + return SliverList.separated( + itemCount: sessions.length, + itemBuilder: (context, index) { + final session = sessions[index]; + final agenda = ref + .watch(agendasViewModelNotifier) + .agendas + .firstWhere((agenda) => session.periodId == agenda.id); + return AgendaScheduleTile( + session: session, + start: agenda.start!, + onTap: () {}, + ); + }, + separatorBuilder: (context, _) => + Constants.smallVerticalGutter.verticalSpace, + ); + } +} + +final _speakersProvider = Provider.autoDispose>((ref) { + throw UnimplementedError(); +}); + +class _Speakers extends ConsumerWidget { + const _Speakers(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final speakers = ref.watch(_speakersProvider); + return SliverList.separated( + itemCount: speakers.length, + itemBuilder: (context, index) { + final speaker = speakers[index]; + final isDayOne = speaker.sessions.first.startTime?.day == 15; + final session = isDayOne + ? ref.watch(dayOneSessionsProvider).firstWhereOrNull( + (session) => session.id == speaker.sessions.first.id) + : ref.watch(dayTwoSessionsProvider).firstWhereOrNull( + (session) => session.id == speaker.sessions.first.id); + + if (session == null) return const SizedBox.shrink(); + return AgendaTalkTile( + speaker: speaker, + session: session, + onTap: () {}, + ); + }, + separatorBuilder: (context, _) => + Constants.smallVerticalGutter.verticalSpace, + ); + } +} diff --git a/packages/conferenceapp/lib/src/features/home/presentation/widgets/agenda_talk_tile.dart b/packages/conferenceapp/lib/src/features/home/presentation/widgets/agenda_talk_tile.dart index 5b90e2e..f07be60 100644 --- a/packages/conferenceapp/lib/src/features/home/presentation/widgets/agenda_talk_tile.dart +++ b/packages/conferenceapp/lib/src/features/home/presentation/widgets/agenda_talk_tile.dart @@ -1,13 +1,17 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; +import 'package:devfest24/src/features/dashboard/model/model.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import '../../../../shared/shared.dart'; class AgendaTalkTile extends StatelessWidget { - const AgendaTalkTile({super.key, this.onTap}); + const AgendaTalkTile( + {super.key, required this.speaker, required this.session, this.onTap}); + final SpeakerDto speaker; + final SessionDto session; final VoidCallback? onTap; @override @@ -39,12 +43,13 @@ class AgendaTalkTile extends StatelessWidget { horizontal: Constants.largeHorizontalGutter, vertical: 14) .r, child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - 'mobile development'.toUpperCase(), + session.categories.first.toUpperCase(), style: DevfestTheme.of(context) .textTheme ?.bodyBody3Medium @@ -58,7 +63,9 @@ class AgendaTalkTile extends StatelessWidget { ), Constants.verticalGutter.verticalSpace, Text( - 'Appreciating the usefulness of football memes in decoding intent', + session.title, + maxLines: 3, + overflow: TextOverflow.ellipsis, style: DevfestTheme.of(context) .textTheme ?.bodyBody1Semibold @@ -67,7 +74,9 @@ class AgendaTalkTile extends StatelessWidget { ), Constants.smallVerticalGutter.verticalSpace, Text( - 'Celebrate the women tech makers at their annual breakfast', + session.descrption, + maxLines: 3, + overflow: TextOverflow.ellipsis, style: DevfestTheme.of(context) .textTheme ?.bodyBody2Medium @@ -75,10 +84,10 @@ class AgendaTalkTile extends StatelessWidget { .applyColor(DevfestColors.grey50.possibleDarkVariant), ), Constants.verticalGutter.verticalSpace, - const SpeakerInfo( - name: 'Samuel Abada', - shortBio: 'Flutter Engineer, Tesla', - avatarUrl: '', + SpeakerInfo( + name: speaker.fullname, + shortBio: '${speaker.title}, ${speaker.company}', + avatarUrl: speaker.imageUrl, ), Constants.verticalGutter.verticalSpace, Row( @@ -116,7 +125,7 @@ class SpeakerInfo extends StatelessWidget { return Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - const Material( + Material( color: DevfestColors.primariesGreen80, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( @@ -126,7 +135,11 @@ class SpeakerInfo extends StatelessWidget { ), child: Padding( padding: EdgeInsets.all(2), - child: FlutterLogo(size: 48), + child: CachedNetworkImage( + imageUrl: avatarUrl, + height: 48, + width: 48, + ), ), ), Constants.horizontalGutter.horizontalSpace, diff --git a/packages/conferenceapp/lib/src/features/home/presentation/widgets/schedule_tile.dart b/packages/conferenceapp/lib/src/features/home/presentation/widgets/schedule_tile.dart index b53260e..11f5268 100644 --- a/packages/conferenceapp/lib/src/features/home/presentation/widgets/schedule_tile.dart +++ b/packages/conferenceapp/lib/src/features/home/presentation/widgets/schedule_tile.dart @@ -1,13 +1,17 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; +import 'package:devfest24/src/features/dashboard/model/model.dart'; import 'package:devfest24/src/shared/extensions.dart'; import 'package:devfest24/src/shared/widgets/icon_text.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; class AgendaScheduleTile extends StatelessWidget { - const AgendaScheduleTile({super.key, this.onTap}); + const AgendaScheduleTile( + {super.key, required this.start, required this.session, this.onTap}); + final DateTime start; + final SessionDto session; final VoidCallback? onTap; @override @@ -33,10 +37,12 @@ class AgendaScheduleTile extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const _Initials(initial: 'W'), + _Initials(initial: session.title[0]), Constants.verticalGutter.verticalSpace, Text( - '๐Ÿ˜˜ Women Tech Makers Breakfast', + session.title, + maxLines: 3, + overflow: TextOverflow.ellipsis, style: DevfestTheme.of(context) .textTheme ?.titleTitle2Semibold @@ -44,7 +50,9 @@ class AgendaScheduleTile extends StatelessWidget { ), Constants.smallVerticalGutter.verticalSpace, Text( - 'Celebrate the women tech makers at their annual breakfast', + session.descrption, + maxLines: 3, + overflow: TextOverflow.ellipsis, style: DevfestTheme.of(context) .textTheme ?.bodyBody2Medium @@ -56,10 +64,10 @@ class AgendaScheduleTile extends StatelessWidget { children: [ IconText( IconsaxOutline.clock, - dateFormat.format(DateTime.now()), + dateFormat.format(start), ), Constants.largeHorizontalGutter.horizontalSpace, - const IconText(IconsaxOutline.location, 'Hall A') + IconText(IconsaxOutline.location, session.venue.id), ], ), ], diff --git a/packages/conferenceapp/lib/src/features/home/presentation/widgets/sponsor_tile.dart b/packages/conferenceapp/lib/src/features/home/presentation/widgets/sponsor_tile.dart index b9ea874..e0f3cf9 100644 --- a/packages/conferenceapp/lib/src/features/home/presentation/widgets/sponsor_tile.dart +++ b/packages/conferenceapp/lib/src/features/home/presentation/widgets/sponsor_tile.dart @@ -3,9 +3,13 @@ import 'package:cave/constants.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; +import '../../../dashboard/model/model.dart'; + class ConferenceSponsorTile extends StatelessWidget { - const ConferenceSponsorTile({super.key, this.linkOnTap}); + const ConferenceSponsorTile( + {super.key, required this.sponsor, this.linkOnTap}); + final SponsorDto sponsor; final VoidCallback? linkOnTap; @override @@ -28,14 +32,15 @@ class ConferenceSponsorTile extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const _SponsorTierTag('Platinum Sponsor'), + _SponsorTierTag(sponsor.category), Padding( padding: const EdgeInsets.symmetric( vertical: Constants.largeVerticalGutter) .h, child: Center( - child: SvgPicture.asset( - 'assets/svgs/Google.svg', + child: CachedNetworkImage( + imageUrl: sponsor.logoUrl, + height: 122.h, ), ), ), @@ -50,7 +55,7 @@ class ConferenceSponsorTile extends StatelessWidget { ), Constants.smallVerticalGutter.verticalSpace, Text( - 'Google', + sponsor.name, style: DevfestTheme.of(context) .textTheme ?.bodyBody1Medium diff --git a/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart index eeb598e..949baf8 100644 --- a/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart @@ -4,13 +4,16 @@ import 'package:devfest24/src/features/more/presentation/widgets/widgets.dart'; import 'package:devfest24/src/routing/routing.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; -class MoreHomeScreen extends StatelessWidget { +import '../../../dashboard/application/application.dart'; + +class MoreHomeScreen extends ConsumerWidget { const MoreHomeScreen({super.key}); @override - Widget build(BuildContext context) { + Widget build(BuildContext context, ref) { return Scaffold( appBar: AppBar(toolbarHeight: 0), body: Column( @@ -21,7 +24,15 @@ class MoreHomeScreen extends StatelessWidget { horizontal: Constants.horizontalMargin.w), child: Column( children: [ - const SignedInUserHeaderTile(), + if (ref.watch(userViewModelNotifier + .select((vm) => vm.user.id.isNotEmpty))) + const SignedInUserHeaderTile() + else + SignedOutUserHeaderTile( + signInOnTap: () { + context.goNamed(Devfest2024Routes.onboardingLogin.name); + }, + ), MoreSection( title: const Text('GENERAL'), options: [ diff --git a/packages/conferenceapp/lib/src/features/more/presentation/screens/my_qr_code.dart b/packages/conferenceapp/lib/src/features/more/presentation/screens/my_qr_code.dart index daed9b2..4224b29 100644 --- a/packages/conferenceapp/lib/src/features/more/presentation/screens/my_qr_code.dart +++ b/packages/conferenceapp/lib/src/features/more/presentation/screens/my_qr_code.dart @@ -1,7 +1,9 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; +import 'package:devfest24/src/features/dashboard/application/application.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; class MyQrCodeScreen extends StatelessWidget { @@ -38,7 +40,15 @@ class MyQrCodeScreen extends StatelessWidget { ?.bodyBody2Medium ?.medium .applyColor(DevfestColors.grey50.possibleDarkVariant), - ) + ), + const Spacer(), + Consumer( + builder: (context, ref, child) => QrImageView( + data: ref + .watch(userViewModelNotifier.select((vm) => vm.user.id)), + size: 296.w), + ), + const Spacer(flex: 3), ], ), ), diff --git a/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart b/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart index 02c0aa6..94b1b97 100644 --- a/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart +++ b/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart @@ -1,15 +1,19 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; import 'package:devfest24/src/shared/shared.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; +import '../../../../routing/routing.dart'; +import '../../../dashboard/application/application.dart'; import '../widgets/widgets.dart'; import 'package:flutter/material.dart'; -class ProfileScreen extends StatelessWidget { +class ProfileScreen extends ConsumerWidget { const ProfileScreen({super.key}); @override - Widget build(BuildContext context) { + Widget build(BuildContext context, ref) { + final user = ref.watch(userViewModelNotifier).user; return Scaffold( extendBodyBehindAppBar: true, appBar: AppBar( @@ -22,12 +26,20 @@ class ProfileScreen extends StatelessWidget { ), body: Column( children: [ - SignedInUserHeaderTile( - height: 300.h, - margin: EdgeInsets.zero, - borderRadius: BorderRadius.zero, - gap: (Constants.verticalGutter * 2).verticalSpace, - ), + if (ref.watch( + userViewModelNotifier.select((vm) => vm.user.id.isNotEmpty))) + SignedInUserHeaderTile( + height: 300.h, + margin: EdgeInsets.zero, + borderRadius: BorderRadius.zero, + gap: (Constants.verticalGutter * 2).verticalSpace, + ) + else + SignedOutUserHeaderTile( + signInOnTap: () { + context.goNamed(Devfest2024Routes.onboardingLogin.name); + }, + ), Expanded( child: SingleChildScrollView( padding: const EdgeInsets.symmetric( @@ -41,24 +53,24 @@ class ProfileScreen extends StatelessWidget { ), child: Column( children: [ - const _ProfileInfoTile( + _ProfileInfoTile( title: '๐Ÿ“ง Email Address', - info: 'samuelabada2@gmail.com', + info: user.emailAddress, ), Constants.verticalGutter.verticalSpace, - const _ProfileInfoTile( + _ProfileInfoTile( title: '๐Ÿคนโ€โ™€๏ธ Area of Expertise', - info: 'Mobile Development', + info: user.role, ), Constants.verticalGutter.verticalSpace, - const _ProfileInfoTile( + _ProfileInfoTile( title: '๐Ÿ˜Š Level of Experience', - info: 'Senior', + info: user.levelOfExpertise, ), Constants.verticalGutter.verticalSpace, - const _ProfileInfoTile( - title: '๐Ÿ˜ Number of Years of Experience', - info: '6+ Years', + _ProfileInfoTile( + title: '๐Ÿ‘• Shirt Size', + info: user.shirtSize, ), ], ), diff --git a/packages/conferenceapp/lib/src/features/more/presentation/widgets/user_header_tiles.dart b/packages/conferenceapp/lib/src/features/more/presentation/widgets/user_header_tiles.dart index 2bcae65..e8d63ba 100644 --- a/packages/conferenceapp/lib/src/features/more/presentation/widgets/user_header_tiles.dart +++ b/packages/conferenceapp/lib/src/features/more/presentation/widgets/user_header_tiles.dart @@ -1,7 +1,9 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; +import 'package:devfest24/src/features/dashboard/application/application.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; class SignedOutUserHeaderTile extends StatelessWidget { const SignedOutUserHeaderTile({super.key, this.signInOnTap}); @@ -154,57 +156,60 @@ class SignedInUserHeaderTile extends StatelessWidget { Radius.circular(Constants.largeVerticalGutter), ), ), - child: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - const _UserInitialTag('s'), - Constants.smallVerticalGutter.verticalSpace, - Text( - 'Samuel Abada', - style: DevfestTheme.of(context) - .textTheme - ?.titleTitle2Semibold - ?.semi - .applyColor(DevfestColors.grey100), - ), - gap ?? const Spacer(), - Row( - children: [ - Expanded( - child: _TicketInfoTile( - title: IconText( - IconsaxOutline.ticket_star, - 'Type: 2 Day Ticket', - textStyle: DevfestTheme.of(context) - .textTheme - ?.bodyBody4Semibold - ?.semi - .applyColor(DevfestColors.grey100), - iconColor: DevfestColors.grey100, - iconSize: 24, + child: Consumer(builder: (context, ref, child) { + final user = ref.watch(userViewModelNotifier.select((vm) => vm.user)); + return Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + _UserInitialTag(user.fullName.split(' ').first[0]), + Constants.smallVerticalGutter.verticalSpace, + Text( + user.fullName, + style: DevfestTheme.of(context) + .textTheme + ?.titleTitle2Semibold + ?.semi + .applyColor(DevfestColors.grey100), + ), + gap ?? const Spacer(), + Row( + children: [ + Expanded( + child: _TicketInfoTile( + title: IconText( + IconsaxOutline.ticket_star, + 'Type: ${user.ticket['title'] ?? ''}', + textStyle: DevfestTheme.of(context) + .textTheme + ?.bodyBody4Semibold + ?.semi + .applyColor(DevfestColors.grey100), + iconColor: DevfestColors.grey100, + iconSize: 24, + ), ), ), - ), - Constants.horizontalGutter.horizontalSpace, - Expanded( - child: _TicketInfoTile( - title: IconText( - IconsaxOutline.ticket_star, - 'ID: 413 012 123', - textStyle: DevfestTheme.of(context) - .textTheme - ?.bodyBody4Semibold - ?.semi - .applyColor(DevfestColors.grey100), - iconColor: DevfestColors.grey100, - iconSize: 24, + Constants.horizontalGutter.horizontalSpace, + Expanded( + child: _TicketInfoTile( + title: IconText( + IconsaxOutline.ticket_star, + 'ID: ${user.id}', + textStyle: DevfestTheme.of(context) + .textTheme + ?.bodyBody4Semibold + ?.semi + .applyColor(DevfestColors.grey100), + iconColor: DevfestColors.grey100, + iconSize: 24, + ), ), ), - ), - ], - ), - ], - ), + ], + ), + ], + ); + }), ), ); } diff --git a/packages/conferenceapp/lib/src/features/reserve/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/reserve/presentation/screens/home.dart index cbe5eb0..2e37f61 100644 --- a/packages/conferenceapp/lib/src/features/reserve/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/reserve/presentation/screens/home.dart @@ -2,12 +2,19 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; import 'package:devfest24/src/features/reserve/presentation/widgets/widgets.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../../shared/shared.dart'; +import '../../../dashboard/application/application.dart'; -class ReserveHomeScreen extends StatelessWidget { +class ReserveHomeScreen extends ConsumerStatefulWidget { const ReserveHomeScreen({super.key}); + @override + ConsumerState createState() => _ReserveHomeScreenState(); +} + +class _ReserveHomeScreenState extends ConsumerState { @override Widget build(BuildContext context) { return Scaffold( @@ -22,7 +29,10 @@ class ReserveHomeScreen extends StatelessWidget { ], ), actions: [ - const CheckInButton(), + CheckInButton( + isLoggedIn: ref.watch( + userViewModelNotifier.select((vm) => vm.user.id.isNotEmpty)), + ), Constants.horizontalMargin.horizontalSpace, ], ), diff --git a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart index e437949..a775c6a 100644 --- a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart @@ -4,11 +4,27 @@ import 'package:devfest24/src/features/schedule/presentation/presentation.dart'; import 'package:devfest24/src/routing/routing.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; -class ScheduleHomeScreen extends StatelessWidget { +import '../../../dashboard/application/application.dart'; + +class ScheduleHomeScreen extends ConsumerStatefulWidget { const ScheduleHomeScreen({super.key}); + @override + ConsumerState createState() => _ScheduleHomeScreenState(); +} + +class _ScheduleHomeScreenState extends ConsumerState { + @override + void initState() { + super.initState(); + + ref.listenManual(dayOneSessionsProvider, (_, next) {}); + ref.listenManual(dayTwoSessionsProvider, (_, next) {}); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -23,7 +39,10 @@ class ScheduleHomeScreen extends StatelessWidget { ], ), actions: [ - const CheckInButton(isLoggedIn: true), + CheckInButton( + isLoggedIn: ref.watch( + userViewModelNotifier.select((vm) => vm.user.id.isNotEmpty)), + ), Constants.horizontalMargin.horizontalSpace, ], ), @@ -31,31 +50,48 @@ class ScheduleHomeScreen extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: Constants.horizontalMargin) .w, - child: CustomScrollView( - slivers: [ - SliverAgendaHeader( - title: const Text('๐Ÿ“† Schedule'), - subtitle: const Text( - 'Our schedule is packed with incredible content all for you!!', + child: RefreshIndicator( + onRefresh: () async { + await ref + .read(agendasViewModelNotifier.notifier) + .fetchAgenda(refresh: true); + }, + child: CustomScrollView( + slivers: [ + SliverAgendaHeader( + title: const Text('๐Ÿ“† Schedule'), + subtitle: const Text( + 'Our schedule is packed with incredible content all for you!!', + ), + onFilterSelected: () {}, + onEventDayChanged: (_) {}, ), - onFilterSelected: () {}, - onEventDayChanged: (_) {}, - ), - SliverList.separated( - itemBuilder: (context, index) => ConferenceScheduleTile( - type: index % 2 == 0 - ? ScheduleTileType.breakout - : ScheduleTileType.session, - onTap: () { - context.goNamed(Devfest2024Routes.scheduleDetails.name); + SliverList.separated( + itemBuilder: (context, index) { + final session = ref.watch(dayOneSessionsProvider)[index]; + final agenda = ref + .watch(agendasViewModelNotifier) + .agendas + .firstWhere((agenda) => session.periodId == agenda.id); + return ConferenceScheduleTile( + start: agenda.start!, + duration: agenda.duration, + session: session, + type: session.categories.isEmpty + ? ScheduleTileType.breakout + : ScheduleTileType.session, + onTap: () { + context.goNamed(Devfest2024Routes.scheduleDetails.name); + }, + ); }, + separatorBuilder: (context, index) => + Constants.verticalGutter.verticalSpace, + itemCount: ref.watch(dayOneSessionsProvider).length, ), - separatorBuilder: (context, index) => - Constants.verticalGutter.verticalSpace, - itemCount: 10, - ), - SliverToBoxAdapter(child: Constants.verticalGutter.verticalSpace), - ], + SliverToBoxAdapter(child: Constants.verticalGutter.verticalSpace), + ], + ), ), ), ); diff --git a/packages/conferenceapp/lib/src/features/schedule/presentation/widgets/conference_schedule_tile.dart b/packages/conferenceapp/lib/src/features/schedule/presentation/widgets/conference_schedule_tile.dart index 863bc85..21598f0 100644 --- a/packages/conferenceapp/lib/src/features/schedule/presentation/widgets/conference_schedule_tile.dart +++ b/packages/conferenceapp/lib/src/features/schedule/presentation/widgets/conference_schedule_tile.dart @@ -4,6 +4,8 @@ import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; +import '../../../dashboard/model/model.dart'; + enum ScheduleTileType { session, breakout } class ConferenceScheduleTile extends StatefulWidget { @@ -11,8 +13,14 @@ class ConferenceScheduleTile extends StatefulWidget { super.key, this.onTap, required this.type, + required this.session, + required this.start, + required this.duration, }); + final SessionDto session; + final DateTime start; + final int duration; final VoidCallback? onTap; final ScheduleTileType type; @@ -77,15 +85,15 @@ class _ConferenceScheduleTileState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - dateFormat.format( - DateTime.now().subtract(const Duration(hours: 5))), + dateFormat.format(widget.start), style: DevfestTheme.of(context) .textTheme ?.bodyBody4Medium ?.medium, ), Text( - dateFormat.format(DateTime.now()), + dateFormat.format( + widget.start.add(Duration(minutes: widget.duration))), style: DevfestTheme.of(context) .textTheme ?.bodyBody4Medium @@ -97,8 +105,9 @@ class _ConferenceScheduleTileState extends State { Expanded( key: _expandedTileKey, child: switch (widget.type) { - ScheduleTileType.session => const _SessionInfo(), - ScheduleTileType.breakout => const _BreakoutScheduleInfo(), + ScheduleTileType.session => _SessionInfo(widget.session), + ScheduleTileType.breakout => + _BreakoutScheduleInfo(widget.session), }, ), ], @@ -109,7 +118,9 @@ class _ConferenceScheduleTileState extends State { } class _SessionInfo extends StatelessWidget { - const _SessionInfo(); + const _SessionInfo(this.session); + + final SessionDto session; @override Widget build(BuildContext context) { @@ -134,7 +145,7 @@ class _SessionInfo extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - 'mobile development'.toUpperCase(), + session.categories.first.toUpperCase(), style: DevfestTheme.of(context) .textTheme ?.bodyBody3Medium @@ -148,7 +159,9 @@ class _SessionInfo extends StatelessWidget { ), Constants.verticalGutter.verticalSpace, Text( - 'Appreciating the usefulness of football memes in decoding intent', + session.title, + maxLines: 3, + overflow: TextOverflow.ellipsis, style: DevfestTheme.of(context) .textTheme ?.bodyBody1Semibold @@ -157,7 +170,9 @@ class _SessionInfo extends StatelessWidget { ), Constants.smallVerticalGutter.verticalSpace, Text( - 'Celebrate the women tech makers at their annual breakfast', + session.descrption, + maxLines: 3, + overflow: TextOverflow.ellipsis, style: DevfestTheme.of(context) .textTheme ?.bodyBody2Medium @@ -165,13 +180,13 @@ class _SessionInfo extends StatelessWidget { .applyColor(DevfestColors.grey50.possibleDarkVariant), ), Constants.verticalGutter.verticalSpace, - const SpeakerInfo( - name: 'Samuel Abada', - shortBio: 'Flutter Engineer, Tesla', - avatarUrl: '', + SpeakerInfo( + name: session.speakers.first.fullname, + shortBio: '${session.speakers.first.title}, ${session.speakers.first.company}', + avatarUrl: session.speakers.first.imageUrl, ), Constants.verticalGutter.verticalSpace, - const IconText(IconsaxOutline.location, 'Hall A'), + IconText(IconsaxOutline.location, session.venue.id), ], ), ), @@ -224,6 +239,8 @@ class SpeakerInfo extends StatelessWidget { (Constants.smallVerticalGutter / 2).verticalSpace, Text( shortBio, + maxLines: 2, + overflow: TextOverflow.ellipsis, style: DevfestTheme.of(context) .textTheme ?.bodyBody3Medium @@ -239,7 +256,9 @@ class SpeakerInfo extends StatelessWidget { } class _BreakoutScheduleInfo extends StatelessWidget { - const _BreakoutScheduleInfo(); + const _BreakoutScheduleInfo(this.session); + + final SessionDto session; @override Widget build(BuildContext context) { @@ -255,16 +274,20 @@ class _BreakoutScheduleInfo extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const _Initials(initial: 'W'), + _Initials(initial: session.title[0]), Constants.verticalGutter.verticalSpace, Text( - '๐Ÿ˜˜ Women Tech Makers Breakfast', + session.title, + maxLines: 3, + overflow: TextOverflow.ellipsis, style: DevfestTheme.of(context).textTheme?.titleTitle2Semibold?.semi, ), Constants.smallVerticalGutter.verticalSpace, Text( - 'Celebrate the women tech makers at their annual breakfast', + session.descrption, + maxLines: 3, + overflow: TextOverflow.ellipsis, style: DevfestTheme.of(context) .textTheme ?.bodyBody2Medium @@ -272,7 +295,7 @@ class _BreakoutScheduleInfo extends StatelessWidget { .copyWith(color: DevfestColors.grey50.possibleDarkVariant), ), Constants.verticalGutter.verticalSpace, - const IconText(IconsaxOutline.location, 'Hall A'), + IconText(IconsaxOutline.location, session.venue.id), ], ), ), diff --git a/packages/conferenceapp/lib/src/features/speakers/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/speakers/presentation/screens/home.dart index d2f7d78..46f0228 100644 --- a/packages/conferenceapp/lib/src/features/speakers/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/speakers/presentation/screens/home.dart @@ -1,15 +1,43 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; +import 'package:devfest24/src/features/dashboard/model/model.dart'; import 'package:devfest24/src/features/speakers/presentation/widgets/widgets.dart'; import 'package:devfest24/src/routing/routing.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../../../shared/shared.dart'; +import '../../../dashboard/application/application.dart'; -class SpeakersHomeScreen extends StatelessWidget { +class SpeakersHomeScreen extends ConsumerStatefulWidget { const SpeakersHomeScreen({super.key}); + @override + ConsumerState createState() => _SpeakersHomeScreenState(); +} + +class _SpeakersHomeScreenState extends ConsumerState { + EventDay _day = EventDay.one; + late ScrollController _scrollController; + Map scrollOffsets = {}; + + @override + void initState() { + super.initState(); + + _scrollController = ScrollController() + ..addListener(() { + scrollOffsets[_day.index] = _scrollController.offset; + }); + } + + @override + void dispose() { + _scrollController.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -24,36 +52,96 @@ class SpeakersHomeScreen extends StatelessWidget { ], ), actions: [ - const CheckInButton(), + CheckInButton( + isLoggedIn: ref.watch( + userViewModelNotifier.select((vm) => vm.user.id.isNotEmpty)), + ), Constants.horizontalMargin.horizontalSpace, ], ), body: Padding( padding: EdgeInsets.symmetric(horizontal: Constants.horizontalMargin.w), - child: CustomScrollView( - slivers: [ - SliverAgendaHeader( - title: const Text('๐ŸŽค Speakers'), - subtitle: const Text( - 'Industry veterans ready to share knowledge with you on their experiences', - ), - onFilterSelected: () {}, - onEventDayChanged: (_) {}, - ), - SliverList.separated( - itemBuilder: (context, index) => SpeakerTile( - onTap: () { - context.goNamed(Devfest2024Routes.speakerDetails.name); + child: RefreshIndicator( + onRefresh: () async { + await ref + .read(speakersViewModelNotifier.notifier) + .fetchSpeakers(refresh: true); + }, + child: CustomScrollView( + controller: _scrollController, + key: PageStorageKey('SpeakersPageScrollView'), + physics: const AlwaysScrollableScrollPhysics(), + slivers: [ + SliverAgendaHeader( + title: const Text('๐ŸŽค Speakers'), + subtitle: const Text( + 'Industry veterans ready to share knowledge with you on their experiences', + ), + eventDay: _day, + onEventDayChanged: (day) { + setState(() { + _day = day; + }); + + if (scrollOffsets.containsKey(_day.index)) { + _scrollController.jumpTo(scrollOffsets[_day.index]!); + } else { + _scrollController.jumpTo(0); + } }, + onFilterSelected: () {}, ), - separatorBuilder: (context, index) => - Constants.verticalGutter.verticalSpace, - itemCount: 20, - ), - SliverToBoxAdapter(child: Constants.verticalGutter.verticalSpace), - ], + [ + ProviderScope( + overrides: [ + _speakersProvider + .overrideWithValue(ref.watch(dayOneSpeakersProvider)), + ], + child: _SpeakersList(), + ), + ProviderScope( + overrides: [ + _speakersProvider + .overrideWithValue(ref.watch(dayTwoSpeakersProvider)), + ], + child: _SpeakersList(), + ), + ].elementAt(_day.index), + SliverToBoxAdapter(child: Constants.verticalGutter.verticalSpace), + ], + ), ), ), ); } } + +final _speakersProvider = Provider.autoDispose>((ref) { + throw UnimplementedError(); +}); + +class _SpeakersList extends ConsumerWidget { + const _SpeakersList(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final speakers = ref.watch(_speakersProvider); + return SliverList.separated( + itemBuilder: (context, index) { + final speaker = speakers[index]; + return SpeakerTile( + speaker: speaker, + onTap: () { + context.goNamed( + Devfest2024Routes.speakerDetails.name, + extra: speaker, + ); + }, + ); + }, + separatorBuilder: (context, index) => + Constants.verticalGutter.verticalSpace, + itemCount: speakers.length, + ); + } +} diff --git a/packages/conferenceapp/lib/src/features/speakers/presentation/screens/speaker_details.dart b/packages/conferenceapp/lib/src/features/speakers/presentation/screens/speaker_details.dart index 16d3fc2..75c45a8 100644 --- a/packages/conferenceapp/lib/src/features/speakers/presentation/screens/speaker_details.dart +++ b/packages/conferenceapp/lib/src/features/speakers/presentation/screens/speaker_details.dart @@ -2,15 +2,27 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; import 'package:cave/ui_utils/container_properties.dart'; import 'package:devfest24/src/features/speakers/presentation/widgets/speaker_social_media.dart'; +import 'package:devfest24/src/shared/shared.dart'; import 'package:devfest24/src/shared/widgets/speaker_talk_info_pill.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:iconoir_flutter/iconoir_flutter.dart' hide Text, List, Key, Radius, Brightness, Map; -class SpeakerDetailsScreen extends StatelessWidget { - const SpeakerDetailsScreen({super.key}); +import '../../../dashboard/model/model.dart'; + +class SpeakerDetailsScreen extends ConsumerStatefulWidget { + const SpeakerDetailsScreen({super.key, required this.speaker}); + + final SpeakerDto speaker; + @override + ConsumerState createState() => + _SpeakerDetailsScreenState(); +} + +class _SpeakerDetailsScreenState extends ConsumerState { @override Widget build(BuildContext context) { return Scaffold( @@ -64,12 +76,11 @@ class SpeakerDetailsScreen extends StatelessWidget { border: Border.all( color: DevfestColors.primariesBlue60, width: 2), ), - child: Image.asset( - 'assets/images/mastersam.png', - semanticLabel: 'Speaker\'s photograph', + padding: EdgeInsets.all(2), + child: CachedNetworkImage( + imageUrl: widget.speaker.imageUrl, height: 56.h, width: 56.w, - fit: BoxFit.cover, ), ), Constants.horizontalGutter.horizontalSpace, @@ -78,7 +89,7 @@ class SpeakerDetailsScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.end, children: [ Text( - 'Samuel Abada', + widget.speaker.fullname, style: DevfestTheme.of(context) .textTheme ?.bodyBody1Semibold @@ -86,7 +97,7 @@ class SpeakerDetailsScreen extends StatelessWidget { ), Constants.smallVerticalGutter.verticalSpace, Text( - 'Flutter Engineer, Tesla', + '${widget.speaker.title}, ${widget.speaker.company}', style: DevfestTheme.of(context) .textTheme ?.bodyBody2Medium @@ -112,17 +123,6 @@ class SpeakerDetailsScreen extends StatelessWidget { ], ), Constants.largeVerticalGutter.verticalSpace, - DevfestFilledButton( - title: Text( - 'Reserve My Spot', - style: DevfestTheme.of(context) - .textTheme - ?.buttonMediumSemibold - ?.semi - .applyColor(DevfestColors.grey100), - ), - ), - Constants.largeVerticalGutter.verticalSpace, Text( 'SPEAKER BIO', style: DevfestTheme.of(context) @@ -133,9 +133,9 @@ class SpeakerDetailsScreen extends StatelessWidget { ), Constants.verticalGutter.verticalSpace, Text( - 'Samuel is a developer from Akure who thinks he is Batman, and unfortunately, with his vast resources and endless wealth he has found a way to balance squashing bugs and the heads of criminals within Nigeria', - style: - DevfestTheme.of(context).textTheme?.bodyBody2Medium?.semi), + widget.speaker.bio, + style: DevfestTheme.of(context).textTheme?.bodyBody2Medium?.semi, + ), Constants.largeVerticalGutter.verticalSpace, Text( 'SPEAKER SOCIALS', @@ -149,20 +149,21 @@ class SpeakerDetailsScreen extends StatelessWidget { Wrap( spacing: 16.w, runSpacing: 16.h, - children: const [ - SpeakerSocialMedia( - icon: Icon( - IconsaxOutline.link_21, - semanticLabel: 'Social Media Link', - ), - onTap: null), - SpeakerSocialMedia(icon: Twitter(), onTap: null), - SpeakerSocialMedia(icon: Facebook(), onTap: null), - SpeakerSocialMedia(icon: Linkedin(), onTap: null), - SpeakerSocialMedia(icon: Behance(), onTap: null), - SpeakerSocialMedia(icon: Github(), onTap: null), - SpeakerSocialMedia(icon: Dribbble(), onTap: null), - ], + children: widget.speaker.links.entries.map((entry) { + final icon = switch (entry.key.toLowerCase()) { + 'github' => Github(), + 'linkedin' => Linkedin(), + 'twitter' => Twitter(), + 'facebook' => Facebook(), + 'dribble' => Dribbble(), + _ => Icon(IconsaxOutline.link_21, + semanticLabel: 'Social Media Link'), + }; + + return SpeakerSocialMedia( + icon: icon, + onTap: () => launchWebUrl(entry.value.toString())); + }).toList(), ) ], ), diff --git a/packages/conferenceapp/lib/src/features/speakers/presentation/widgets/speaker_tile.dart b/packages/conferenceapp/lib/src/features/speakers/presentation/widgets/speaker_tile.dart index 4e51884..de5b3f1 100644 --- a/packages/conferenceapp/lib/src/features/speakers/presentation/widgets/speaker_tile.dart +++ b/packages/conferenceapp/lib/src/features/speakers/presentation/widgets/speaker_tile.dart @@ -1,11 +1,13 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; +import 'package:devfest24/src/features/dashboard/model/model.dart'; import 'package:flutter/material.dart'; import '../../../../shared/shared.dart'; class SpeakerTile extends StatelessWidget { - const SpeakerTile({super.key, this.onTap}); + const SpeakerTile({super.key, required this.speaker, this.onTap}); + final SpeakerDto speaker; final VoidCallback? onTap; @override @@ -18,10 +20,10 @@ class SpeakerTile extends StatelessWidget { borderRadius: const BorderRadius.all( Radius.circular(Constants.verticalGutter), ), - child: const SpeakerInfo( - name: 'Samuel Abada', - shortBio: 'Flutter Engineer, Tesla', - avatarUrl: '', + child: SpeakerInfo( + name: speaker.fullname, + shortBio: '${speaker.title}, ${speaker.company}', + avatarUrl: speaker.imageUrl, ), ), ); @@ -45,17 +47,22 @@ class SpeakerInfo extends StatelessWidget { return Row( mainAxisAlignment: MainAxisAlignment.start, children: [ - const Material( + Material( color: DevfestColors.primariesGreen80, - shape: RoundedRectangleBorder( + shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(Constants.smallVerticalGutter), ), side: BorderSide(color: DevfestColors.primariesBlue50, width: 2), ), child: Padding( - padding: EdgeInsets.all(2), - child: FlutterLogo(size: 48), + padding: const EdgeInsets.all(2), + child: CachedNetworkImage( + imageUrl: avatarUrl, + height: 48.h, + width: 48.w, + ), + // FlutterLogo(size: 48), ), ), Constants.horizontalGutter.horizontalSpace, diff --git a/packages/conferenceapp/lib/src/routing/extra_codec.dart b/packages/conferenceapp/lib/src/routing/extra_codec.dart new file mode 100644 index 0000000..8c03cf3 --- /dev/null +++ b/packages/conferenceapp/lib/src/routing/extra_codec.dart @@ -0,0 +1,49 @@ +import 'dart:convert'; + +import '../features/dashboard/model/model.dart'; + +class ConferenceExtraCodec extends Codec { + const ConferenceExtraCodec({ + this.decoder = const _ConferenceExtraDecoder(), + this.encoder = const _ConferenceExtraEncoder(), + }); + + @override + final Converter decoder; + + @override + final Converter encoder; +} + +class _ConferenceExtraDecoder extends Converter { + const _ConferenceExtraDecoder(); + + @override + Object? convert(Object? input) { + if (input == null) { + return null; + } + final List inputAsList = input as List; + return switch (inputAsList[0]) { + 'SpeakerDto' => + SpeakerDto.fromJson(inputAsList[1] as Map), + _ => throw FormatException('Unable to parse input: $input'), + }; + } +} + +class _ConferenceExtraEncoder extends Converter { + const _ConferenceExtraEncoder(); + + @override + Object? convert(Object? input) { + if (input == null) { + return null; + } + + return switch (input) { + SpeakerDto dto => ['SpeakerDto', dto.toJson()], + _ => throw FormatException('Cannot encode type ${input.runtimeType}'), + }; + } +} diff --git a/packages/conferenceapp/lib/src/routing/router.dart b/packages/conferenceapp/lib/src/routing/router.dart index 5a27c10..d128d5c 100644 --- a/packages/conferenceapp/lib/src/routing/router.dart +++ b/packages/conferenceapp/lib/src/routing/router.dart @@ -4,7 +4,9 @@ import 'package:devfest24/src/features/more/presentation/presentation.dart'; import 'package:devfest24/src/features/onboarding/presentation/presentation.dart'; import 'package:devfest24/src/features/schedule/presentation/presentation.dart'; import 'package:devfest24/src/features/speakers/presentation/presentation.dart'; +import 'package:devfest24/src/routing/extra_codec.dart'; +import '../features/dashboard/model/model.dart'; import 'routes.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -27,6 +29,7 @@ class Devfest2024Router { return GoRouter( navigatorKey: rootNavigatorKey, initialLocation: '/', + extraCodec: const ConferenceExtraCodec(), routes: [ GoRoute( path: '/${Devfest2024Routes.onboardingHome.path}', @@ -62,7 +65,9 @@ class Devfest2024Router { GoRoute( path: Devfest2024Routes.speakerDetails.path, name: Devfest2024Routes.speakerDetails.name, - builder: (context, state) => const SpeakerDetailsScreen(), + builder: (context, state) => SpeakerDetailsScreen( + speaker: state.extra as SpeakerDto, + ), ), GoRoute( path: Devfest2024Routes.scheduleDetails.path, diff --git a/packages/conferenceapp/lib/src/shared/extensions.dart b/packages/conferenceapp/lib/src/shared/extensions.dart index 3e4fdc9..48485c5 100644 --- a/packages/conferenceapp/lib/src/shared/extensions.dart +++ b/packages/conferenceapp/lib/src/shared/extensions.dart @@ -26,3 +26,13 @@ extension DevfestColorsX on Color { return this; } } + +extension ListX on List { + List safeSublist(int length) { + try { + return sublist(0, length); + } on RangeError { + return this; + } + } +} diff --git a/packages/conferenceapp/lib/src/shared/shared.dart b/packages/conferenceapp/lib/src/shared/shared.dart index 9728d84..5618258 100644 --- a/packages/conferenceapp/lib/src/shared/shared.dart +++ b/packages/conferenceapp/lib/src/shared/shared.dart @@ -1,3 +1,4 @@ export 'ui_model/ui_state_model.dart'; export 'widgets/widgets.dart'; export 'extensions.dart'; +export 'utility.dart'; diff --git a/packages/conferenceapp/lib/src/shared/utility.dart b/packages/conferenceapp/lib/src/shared/utility.dart new file mode 100644 index 0000000..1c34816 --- /dev/null +++ b/packages/conferenceapp/lib/src/shared/utility.dart @@ -0,0 +1,11 @@ +import 'dart:developer'; + +import 'package:url_launcher/url_launcher.dart'; + +Future launchWebUrl(String path) async { + final uri = Uri.parse(path); + + if (!await launchUrl(uri)) { + log('Failed to launch url'); + } +} diff --git a/packages/conferenceapp/lib/src/shared/widgets/agenda_header.dart b/packages/conferenceapp/lib/src/shared/widgets/agenda_header.dart index 333acd4..cbaaff2 100644 --- a/packages/conferenceapp/lib/src/shared/widgets/agenda_header.dart +++ b/packages/conferenceapp/lib/src/shared/widgets/agenda_header.dart @@ -100,8 +100,8 @@ class AgendaHeader extends StatelessWidget { ), ], ), - Constants.verticalGutter.verticalSpace, ], + Constants.verticalGutter.verticalSpace, ], ), ); @@ -183,6 +183,7 @@ class _SliverAgendaHeaderState extends State { color: DevfestTheme.of(context).backgroundColor, child: AgendaHeader( title: widget.title, + eventDay: widget.eventDay, subtitle: switch (hideHeaders) { true => null, false => widget.subtitle, @@ -213,6 +214,7 @@ class _SliverAgendaHeaderState extends State { }, titleStyle: widget.titleStyle, onFilterSelected: widget.onFilterSelected, + eventDay: widget.eventDay, onEventDayChanged: widget.onEventDayChanged, gutter: switch (hideHeaders) { true => Constants.smallVerticalGutter.verticalSpace, @@ -233,6 +235,7 @@ class _SliverAgendaHeaderState extends State { }, titleStyle: widget.titleStyle, onFilterSelected: widget.onFilterSelected, + eventDay: widget.eventDay, onEventDayChanged: widget.onEventDayChanged, gutter: switch (hideHeaders) { true => Constants.smallVerticalGutter.verticalSpace, diff --git a/packages/conferenceapp/pubspec.lock b/packages/conferenceapp/pubspec.lock index e834a7c..7ab6dc4 100644 --- a/packages/conferenceapp/pubspec.lock +++ b/packages/conferenceapp/pubspec.lock @@ -33,6 +33,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + cached_network_image: + dependency: transitive + description: + name: cached_network_image + sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916" + url: "https://pub.dev" + source: hosted + version: "3.4.1" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" + url: "https://pub.dev" + source: hosted + version: "4.1.1" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062" + url: "https://pub.dev" + source: hosted + version: "1.3.1" cached_value: dependency: transitive description: @@ -80,6 +104,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: ec30d999af904f33454ba22ed9a86162b35e52b44ac4807d1d93c288041d7d27 + url: "https://pub.dev" + source: hosted + version: "3.0.5" dio: dependency: transitive description: @@ -168,6 +200,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.18.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -181,14 +221,22 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" + url: "https://pub.dev" + source: hosted + version: "3.4.1" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" + sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" flutter_riverpod: dependency: "direct main" description: @@ -283,10 +331,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: "5cf5fdcf853b0629deb35891c7af643be900c3dcaed7489009f9e7dbcfe55ab6" + sha256: "6f1b756f6e863259a99135ff3c95026c3cdca17d10ebef2bba2261a25ddc8bbc" url: "https://pub.dev" source: hosted - version: "14.2.8" + version: "14.3.0" http: dependency: transitive description: @@ -355,10 +403,10 @@ packages: dependency: transitive description: name: lints - sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" + sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" url: "https://pub.dev" source: hosted - version: "4.0.0" + version: "5.0.0" logging: dependency: transitive description: @@ -407,6 +455,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.2.3" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" package_info_plus: dependency: "direct main" description: @@ -511,6 +567,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + qr: + dependency: transitive + description: + name: qr + sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + qr_flutter: + dependency: transitive + description: + name: qr_flutter + sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097" + url: "https://pub.dev" + source: hosted + version: "4.1.0" riverpod: dependency: transitive description: @@ -519,6 +591,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.5.1" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" + url: "https://pub.dev" + source: hosted + version: "0.28.0" shared_preferences: dependency: transitive description: @@ -575,6 +655,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.1" + shimmer: + dependency: transitive + description: + name: shimmer + sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9" + url: "https://pub.dev" + source: hosted + version: "3.0.0" sky_engine: dependency: transitive description: flutter @@ -588,6 +676,54 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: "79a297dc3cc137e758c6a4baf83342b039e5a6d2436fcdf3f96a00adaaf2ad62" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + sqflite_android: + dependency: transitive + description: + name: sqflite_android + sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "4468b24876d673418a7b7147e5a08a715b4998a7ae69227acafaab762e0e5490" + url: "https://pub.dev" + source: hosted + version: "2.5.4+5" + sqflite_darwin: + dependency: transitive + description: + name: sqflite_darwin + sha256: "769733dddf94622d5541c73e4ddc6aa7b252d865285914b6fcd54a63c4b4f027" + url: "https://pub.dev" + source: hosted + version: "2.4.1-1" + sqflite_platform_interface: + dependency: transitive + description: + name: sqflite_platform_interface + sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" + url: "https://pub.dev" + source: hosted + version: "2.4.0" stack_trace: dependency: transitive description: @@ -620,6 +756,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" + url: "https://pub.dev" + source: hosted + version: "3.3.0+3" term_glyph: dependency: transitive description: @@ -644,6 +788,78 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" + url: "https://pub.dev" + source: hosted + version: "6.3.1" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "8fc3bae0b68c02c47c5c86fa8bfa74471d42687b0eded01b78de87872db745e2" + url: "https://pub.dev" + source: hosted + version: "6.3.12" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: e43b677296fadce447e987a2f519dcf5f6d1e527dc35d01ffab4fff5b8a7063e + url: "https://pub.dev" + source: hosted + version: "6.3.1" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: e2b9622b4007f97f504cd64c0128309dfb978ae66adbe944125ed9e1750f06af + url: "https://pub.dev" + source: hosted + version: "3.2.0" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "769549c999acdb42b8bcfa7c43d72bf79a382ca7441ab18a808e101149daf672" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "49c10f879746271804767cb45551ec5592cdab00ee105c06dddde1a98f73b185" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + url: "https://pub.dev" + source: hosted + version: "4.5.1" vector_graphics: dependency: transitive description: diff --git a/packages/conferenceapp/pubspec.yaml b/packages/conferenceapp/pubspec.yaml index dae192a..72f80ed 100644 --- a/packages/conferenceapp/pubspec.yaml +++ b/packages/conferenceapp/pubspec.yaml @@ -19,17 +19,19 @@ dependencies: flutter: sdk: flutter flutter_riverpod: ^2.5.1 - go_router: ^14.2.8 + go_router: ^14.3.0 intl: ^0.19.0 mesh: ^0.4.1 package_info_plus: ^8.0.2 path_provider: ^2.1.4 iconoir_flutter: ^7.9.0 + url_launcher: ^6.3.1 + dependency_overrides: firebase_core: 3.3.0 dev_dependencies: - flutter_lints: ^4.0.0 + flutter_lints: ^5.0.0 flutter_test: sdk: flutter @@ -38,7 +40,6 @@ flutter: assets: - assets/svgs/ - - assets/images/ # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in From 420c78d9d5537e5d4c39ef761b2f66c1f67f3038 Mon Sep 17 00:00:00 2001 From: Sebastine Odeh Date: Sat, 12 Oct 2024 17:12:57 +0100 Subject: [PATCH 2/8] linting --- .../features/more/presentation/screens/profile.dart | 10 +++++----- .../presentation/widgets/conference_schedule_tile.dart | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart b/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart index 94b1b97..fde14f6 100644 --- a/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart +++ b/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart @@ -53,22 +53,22 @@ class ProfileScreen extends ConsumerWidget { ), child: Column( children: [ - _ProfileInfoTile( + _ProfileInfoTile( title: '๐Ÿ“ง Email Address', - info: user.emailAddress, + info: user.emailAddress, ), Constants.verticalGutter.verticalSpace, - _ProfileInfoTile( + _ProfileInfoTile( title: '๐Ÿคนโ€โ™€๏ธ Area of Expertise', info: user.role, ), Constants.verticalGutter.verticalSpace, - _ProfileInfoTile( + _ProfileInfoTile( title: '๐Ÿ˜Š Level of Experience', info: user.levelOfExpertise, ), Constants.verticalGutter.verticalSpace, - _ProfileInfoTile( + _ProfileInfoTile( title: '๐Ÿ‘• Shirt Size', info: user.shirtSize, ), diff --git a/packages/conferenceapp/lib/src/features/schedule/presentation/widgets/conference_schedule_tile.dart b/packages/conferenceapp/lib/src/features/schedule/presentation/widgets/conference_schedule_tile.dart index 21598f0..6b1da18 100644 --- a/packages/conferenceapp/lib/src/features/schedule/presentation/widgets/conference_schedule_tile.dart +++ b/packages/conferenceapp/lib/src/features/schedule/presentation/widgets/conference_schedule_tile.dart @@ -182,7 +182,8 @@ class _SessionInfo extends StatelessWidget { Constants.verticalGutter.verticalSpace, SpeakerInfo( name: session.speakers.first.fullname, - shortBio: '${session.speakers.first.title}, ${session.speakers.first.company}', + shortBio: + '${session.speakers.first.title}, ${session.speakers.first.company}', avatarUrl: session.speakers.first.imageUrl, ), Constants.verticalGutter.verticalSpace, From 070decdf77f8984a3d3208963316bea2a8ff21a3 Mon Sep 17 00:00:00 2001 From: Sebastine Odeh Date: Tue, 22 Oct 2024 21:06:20 +0100 Subject: [PATCH 3/8] linting --- .../conferenceapp/lib/src/routing/router.dart | 17 ++++++++--------- .../lib/src/shared/widgets/check_in_button.dart | 6 +++++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/conferenceapp/lib/src/routing/router.dart b/packages/conferenceapp/lib/src/routing/router.dart index d128d5c..8cac1bb 100644 --- a/packages/conferenceapp/lib/src/routing/router.dart +++ b/packages/conferenceapp/lib/src/routing/router.dart @@ -30,6 +30,14 @@ class Devfest2024Router { navigatorKey: rootNavigatorKey, initialLocation: '/', extraCodec: const ConferenceExtraCodec(), + redirect: (context, state) async { + final token = await ConferenceAppStorageService.instance.userToken; + if (token.isEmpty) { + return '/${Devfest2024Routes.onboardingHome.path}'; + } + + return null; + }, routes: [ GoRoute( path: '/${Devfest2024Routes.onboardingHome.path}', @@ -52,15 +60,6 @@ class Devfest2024Router { path: '/', name: Devfest2024Routes.dashboard.name, builder: (context, state) => const DashboardScreen(), - redirect: (context, state) async { - final token = - await ConferenceAppStorageService.instance.userToken; - if (token.isEmpty) { - return '/${Devfest2024Routes.onboardingHome.path}'; - } - - return null; - }, routes: [ GoRoute( path: Devfest2024Routes.speakerDetails.path, diff --git a/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart b/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart index 28e3ac2..6dd4ff2 100644 --- a/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart +++ b/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart @@ -1,5 +1,7 @@ import 'package:cave/cave.dart'; +import 'package:devfest24/src/routing/routing.dart'; import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; class CheckInButton extends StatelessWidget { const CheckInButton({ @@ -19,7 +21,9 @@ class CheckInButton extends StatelessWidget { width: 113.w, child: isLoggedIn ? _CheckInButton(onCheckInTap) - : _LoginCheckInButton(onCheckInTap), + : _LoginCheckInButton(() { + context.goNamed(Devfest2024Routes.onboardingLogin.name); + }), ); } } From 482571ed852aa13ce782981efe841b3c06f482cf Mon Sep 17 00:00:00 2001 From: Codefarmer Date: Wed, 23 Oct 2024 20:56:31 +0300 Subject: [PATCH 4/8] chore: remove dark theme from volunteer app --- packages/catalog/pubspec.lock | 344 ++++++++++++++++++- packages/volunteerapp/lib/volunteer_app.dart | 23 -- packages/volunteerapp/pubspec.lock | 144 ++++++++ 3 files changed, 484 insertions(+), 27 deletions(-) diff --git a/packages/catalog/pubspec.lock b/packages/catalog/pubspec.lock index 377776e..c75cb27 100644 --- a/packages/catalog/pubspec.lock +++ b/packages/catalog/pubspec.lock @@ -118,6 +118,30 @@ packages: url: "https://pub.dev" source: hosted version: "8.9.2" + cached_network_image: + dependency: transitive + description: + name: cached_network_image + sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916" + url: "https://pub.dev" + source: hosted + version: "3.4.1" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" + url: "https://pub.dev" + source: hosted + version: "4.1.1" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062" + url: "https://pub.dev" + source: hosted + version: "1.3.1" cave: dependency: "direct main" description: @@ -205,6 +229,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + dio: + dependency: transitive + description: + name: dio + sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260" + url: "https://pub.dev" + source: hosted + version: "5.7.0" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8" + url: "https://pub.dev" + source: hosted + version: "2.0.0" email_validator: dependency: transitive description: @@ -221,6 +261,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" + source: hosted + version: "2.1.3" ficonsax: dependency: transitive description: @@ -258,6 +306,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" + url: "https://pub.dev" + source: hosted + version: "3.4.1" flutter_lints: dependency: "direct dev" description: @@ -274,6 +330,54 @@ packages: url: "https://pub.dev" source: hosted version: "5.9.1" + flutter_secure_storage: + dependency: transitive + description: + name: flutter_secure_storage + sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0" + url: "https://pub.dev" + source: hosted + version: "9.2.2" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: "4d91bfc23047422cbcd73ac684bc169859ee766482517c22172c86596bf1464b" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + sha256: "1693ab11121a5f925bbea0be725abfcfbbcf36c1e29e571f84a0c0f436147a81" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8 + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709 + url: "https://pub.dev" + source: hosted + version: "3.1.2" flutter_shaders: dependency: transitive description: @@ -376,10 +480,10 @@ packages: dependency: transitive description: name: js - sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 url: "https://pub.dev" source: hosted - version: "0.7.1" + version: "0.6.7" json_annotation: dependency: transitive description: @@ -484,6 +588,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" package_config: dependency: transitive description: @@ -508,6 +620,54 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.1" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: fec0d61223fba3154d87759e3cc27fe2c8dc498f6386c6d6fc80d1afdd1bf378 + url: "https://pub.dev" + source: hosted + version: "2.1.4" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: c464428172cb986b758c6d1724c603097febb8fb855aa265aeecc9280c294d4a + url: "https://pub.dev" + source: hosted + version: "2.2.12" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + url: "https://pub.dev" + source: hosted + version: "2.4.0" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" petitparser: dependency: transitive description: @@ -516,6 +676,14 @@ packages: url: "https://pub.dev" source: hosted version: "6.0.2" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" plugin_platform_interface: dependency: transitive description: @@ -548,6 +716,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + qr: + dependency: transitive + description: + name: qr + sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + qr_flutter: + dependency: transitive + description: + name: qr_flutter + sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097" + url: "https://pub.dev" + source: hosted + version: "4.1.0" resizable_widget: dependency: transitive description: @@ -556,6 +740,70 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.5" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" + url: "https://pub.dev" + source: hosted + version: "0.28.0" + shared_preferences: + dependency: transitive + description: + name: shared_preferences + sha256: "746e5369a43170c25816cc472ee016d3a66bc13fcf430c0bc41ad7b4b2922051" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "3b9febd815c9ca29c9e3520d50ec32f49157711e143b7a4ca039eb87e8ade5ab" + url: "https://pub.dev" + source: hosted + version: "2.3.3" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "07e050c7cd39bad516f8d64c455f04508d09df104be326d8c02551590a0d513d" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: d2ca4132d3946fec2184261726b355836a82c33d7d5b67af32692aff18a4684e + url: "https://pub.dev" + source: hosted + version: "2.4.2" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" shelf: dependency: transitive description: @@ -572,6 +820,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + shimmer: + dependency: transitive + description: + name: shimmer + sha256: "5f88c883a22e9f9f299e5ba0e4f7e6054857224976a5d9f839d4ebdc94a14ac9" + url: "https://pub.dev" + source: hosted + version: "3.0.0" sky_engine: dependency: transitive description: flutter @@ -593,6 +849,54 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: "79a297dc3cc137e758c6a4baf83342b039e5a6d2436fcdf3f96a00adaaf2ad62" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + sqflite_android: + dependency: transitive + description: + name: sqflite_android + sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "4468b24876d673418a7b7147e5a08a715b4998a7ae69227acafaab762e0e5490" + url: "https://pub.dev" + source: hosted + version: "2.5.4+5" + sqflite_darwin: + dependency: transitive + description: + name: sqflite_darwin + sha256: "769733dddf94622d5541c73e4ddc6aa7b252d865285914b6fcd54a63c4b4f027" + url: "https://pub.dev" + source: hosted + version: "2.4.1-1" + sqflite_platform_interface: + dependency: transitive + description: + name: sqflite_platform_interface + sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" + url: "https://pub.dev" + source: hosted + version: "2.4.0" stack_trace: dependency: transitive description: @@ -625,6 +929,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" + url: "https://pub.dev" + source: hosted + version: "3.3.0+3" term_glyph: dependency: transitive description: @@ -657,6 +969,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + url: "https://pub.dev" + source: hosted + version: "4.5.1" vector_graphics: dependency: transitive description: @@ -753,6 +1073,22 @@ packages: url: "https://pub.dev" source: hosted version: "3.8.0" + win32: + dependency: transitive + description: + name: win32 + sha256: e1d0cc62e65dc2561f5071fcbccecf58ff20c344f8f3dc7d4922df372a11df1f + url: "https://pub.dev" + source: hosted + version: "5.7.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" xml: dependency: transitive description: @@ -770,5 +1106,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.5.0-259.0.dev <4.0.0" - flutter: ">=3.22.0" + dart: ">=3.5.0 <4.0.0" + flutter: ">=3.24.0" diff --git a/packages/volunteerapp/lib/volunteer_app.dart b/packages/volunteerapp/lib/volunteer_app.dart index 7da9fb0..0545318 100644 --- a/packages/volunteerapp/lib/volunteer_app.dart +++ b/packages/volunteerapp/lib/volunteer_app.dart @@ -62,29 +62,6 @@ class _ConferenceAppState extends ConsumerState { DevFestThemeData.light(), ], ), - darkTheme: ThemeData( - colorScheme: ColorScheme.fromSeed( - seedColor: Colors.deepPurple, - brightness: Brightness.dark, - surface: DevFestThemeData.dark().backgroundColor, - ), - appBarTheme: AppBarTheme( - elevation: 0, - color: DevFestThemeData.dark().backgroundColor, - surfaceTintColor: Colors.transparent, - scrolledUnderElevation: 0, - ), - scaffoldBackgroundColor: DevFestThemeData.dark().backgroundColor, - useMaterial3: true, - textTheme: const TextTheme( - displayMedium: TextStyle(color: DevfestColors.grey100), - ), - extensions: >[ - /// Use the below format for raw theme data - /// DevFestTheme(textTheme: DevfestTextTheme()), - DevFestThemeData.dark(), - ], - ), ); }, ), diff --git a/packages/volunteerapp/pubspec.lock b/packages/volunteerapp/pubspec.lock index f312a5f..0159dcf 100644 --- a/packages/volunteerapp/pubspec.lock +++ b/packages/volunteerapp/pubspec.lock @@ -33,6 +33,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + cached_network_image: + dependency: transitive + description: + name: cached_network_image + sha256: "7c1183e361e5c8b0a0f21a28401eecdbde252441106a9816400dd4c2b2424916" + url: "https://pub.dev" + source: hosted + version: "3.4.1" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: "35814b016e37fbdc91f7ae18c8caf49ba5c88501813f73ce8a07027a395e2829" + url: "https://pub.dev" + source: hosted + version: "4.1.1" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: "980842f4e8e2535b8dbd3d5ca0b1f0ba66bf61d14cc3a17a9b4788a3685ba062" + url: "https://pub.dev" + source: hosted + version: "1.3.1" cave: dependency: "direct main" description: @@ -72,6 +96,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" dio: dependency: transitive description: @@ -160,6 +192,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.18.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" flutter: dependency: "direct main" description: flutter @@ -173,6 +213,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "400b6592f16a4409a7f2bb929a9a7e38c72cceb8ffb99ee57bbf2cb2cecf8386" + url: "https://pub.dev" + source: hosted + version: "3.4.1" flutter_lints: dependency: "direct dev" description: @@ -383,6 +431,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.2.3" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" path: dependency: transitive description: @@ -471,6 +527,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + qr: + dependency: transitive + description: + name: qr + sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + qr_flutter: + dependency: transitive + description: + name: qr_flutter + sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097" + url: "https://pub.dev" + source: hosted + version: "4.1.0" riverpod: dependency: transitive description: @@ -479,6 +551,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.5.1" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" + url: "https://pub.dev" + source: hosted + version: "0.28.0" shared_preferences: dependency: transitive description: @@ -556,6 +636,54 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: "79a297dc3cc137e758c6a4baf83342b039e5a6d2436fcdf3f96a00adaaf2ad62" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + sqflite_android: + dependency: transitive + description: + name: sqflite_android + sha256: "78f489aab276260cdd26676d2169446c7ecd3484bbd5fead4ca14f3ed4dd9ee3" + url: "https://pub.dev" + source: hosted + version: "2.4.0" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "4468b24876d673418a7b7147e5a08a715b4998a7ae69227acafaab762e0e5490" + url: "https://pub.dev" + source: hosted + version: "2.5.4+5" + sqflite_darwin: + dependency: transitive + description: + name: sqflite_darwin + sha256: "769733dddf94622d5541c73e4ddc6aa7b252d865285914b6fcd54a63c4b4f027" + url: "https://pub.dev" + source: hosted + version: "2.4.1-1" + sqflite_platform_interface: + dependency: transitive + description: + name: sqflite_platform_interface + sha256: "8dd4515c7bdcae0a785b0062859336de775e8c65db81ae33dd5445f35be61920" + url: "https://pub.dev" + source: hosted + version: "2.4.0" stack_trace: dependency: transitive description: @@ -588,6 +716,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "69fe30f3a8b04a0be0c15ae6490fc859a78ef4c43ae2dd5e8a623d45bfcf9225" + url: "https://pub.dev" + source: hosted + version: "3.3.0+3" term_glyph: dependency: transitive description: @@ -612,6 +748,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + url: "https://pub.dev" + source: hosted + version: "4.5.1" vector_graphics: dependency: transitive description: From 3595087dcda3f204507f4944032a88d322c8da5c Mon Sep 17 00:00:00 2001 From: Sebastine Odeh Date: Sat, 26 Oct 2024 08:54:33 +0100 Subject: [PATCH 5/8] - refactored router to navigator 1.0 - added internet permission to android manifest --- .../lib/utils/exceptions/base_exception.dart | 2 - .../lib/utils/network/data_transformer.dart | 1 - .../utils/services/local_storage_service.dart | 12 ++ .../android/app/src/main/AndroidManifest.xml | 23 +-- .../conferenceapp/lib/conference_app.dart | 23 ++- .../application/user/view_model.dart | 2 +- .../presentation/screens/dashboard.dart | 3 + .../home/presentation/screens/home.dart | 2 + .../more/presentation/screens/home.dart | 13 +- .../more/presentation/screens/my_qr_code.dart | 20 +- .../more/presentation/screens/profile.dart | 7 +- .../more/presentation/screens/venue_map.dart | 4 +- .../onboarding/presentation/screens/home.dart | 98 +++++----- .../presentation/screens/login.dart | 9 +- .../presentation/screens/signature.dart | 6 +- .../schedule/presentation/screens/home.dart | 3 +- .../screens/schedule_details.dart | 4 +- .../speakers/presentation/screens/home.dart | 6 +- .../presentation/screens/speaker_details.dart | 3 +- .../lib/src/routing/extra_codec.dart | 49 ----- .../conferenceapp/lib/src/routing/router.dart | 182 +++++++++++------- .../conferenceapp/lib/src/routing/routes.dart | 15 -- .../lib/src/routing/routing.dart | 1 - .../src/shared/ui_model/ui_state_model.dart | 5 - .../src/shared/widgets/check_in_button.dart | 6 +- packages/conferenceapp/pubspec.lock | 20 +- packages/conferenceapp/pubspec.yaml | 3 +- 27 files changed, 264 insertions(+), 258 deletions(-) delete mode 100644 packages/conferenceapp/lib/src/routing/extra_codec.dart delete mode 100644 packages/conferenceapp/lib/src/routing/routes.dart diff --git a/packages/cave/lib/utils/exceptions/base_exception.dart b/packages/cave/lib/utils/exceptions/base_exception.dart index 502fbd3..08141a9 100644 --- a/packages/cave/lib/utils/exceptions/base_exception.dart +++ b/packages/cave/lib/utils/exceptions/base_exception.dart @@ -1,6 +1,4 @@ import 'package:cave/cave.dart'; -import 'client_exception.dart'; -import 'empty_exception.dart'; base class Devfest2024Exception implements Exception { const Devfest2024Exception(); diff --git a/packages/cave/lib/utils/network/data_transformer.dart b/packages/cave/lib/utils/network/data_transformer.dart index e1cfc1d..65f9fd0 100644 --- a/packages/cave/lib/utils/network/data_transformer.dart +++ b/packages/cave/lib/utils/network/data_transformer.dart @@ -1,6 +1,5 @@ import 'package:cave/cave.dart'; import 'package:flutter/foundation.dart'; -import '../exceptions/exceptions.dart'; typedef Devfest2024ExceptionOr = Either; typedef FutureDevfest2024ExceptionOr = Future>; diff --git a/packages/cave/lib/utils/services/local_storage_service.dart b/packages/cave/lib/utils/services/local_storage_service.dart index 3d8cbb1..dcbe3cf 100644 --- a/packages/cave/lib/utils/services/local_storage_service.dart +++ b/packages/cave/lib/utils/services/local_storage_service.dart @@ -17,6 +17,9 @@ final class ConferenceAppStorageService { iOptions: _getIosOptions(), ); + SharedPreferencesAsync get _sharedPreferencesInstance => + SharedPreferencesAsync(); + Future setUserToken(String token) async { return await _securedStorageInstance.write(key: 'user-token', value: token); } @@ -24,4 +27,13 @@ final class ConferenceAppStorageService { Future get userToken async { return await _securedStorageInstance.read(key: 'user-token') ?? ''; } + + Future setIsFirstLaunch(bool isFirstLaunch) async { + return await _sharedPreferencesInstance.setBool( + 'is-first-launch', isFirstLaunch); + } + + Future get isFirstLaunch async { + return await _sharedPreferencesInstance.getBool('is-first-launch') ?? true; + } } diff --git a/packages/conferenceapp/android/app/src/main/AndroidManifest.xml b/packages/conferenceapp/android/app/src/main/AndroidManifest.xml index ca45c90..7076b91 100644 --- a/packages/conferenceapp/android/app/src/main/AndroidManifest.xml +++ b/packages/conferenceapp/android/app/src/main/AndroidManifest.xml @@ -1,28 +1,29 @@ + + + android:icon="@mipmap/ic_launcher" + android:label="Devfest24"> + android:name="io.flutter.embedding.android.NormalTheme" + android:resource="@style/NormalTheme" /> - - + + - - + + diff --git a/packages/conferenceapp/lib/conference_app.dart b/packages/conferenceapp/lib/conference_app.dart index 317f98f..5cf3637 100644 --- a/packages/conferenceapp/lib/conference_app.dart +++ b/packages/conferenceapp/lib/conference_app.dart @@ -4,6 +4,8 @@ import 'package:devfest24/src/routing/routing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'src/features/onboarding/presentation/presentation.dart'; + class ConferenceApp extends ConsumerStatefulWidget { const ConferenceApp({super.key}); @@ -17,14 +19,25 @@ class _ConferenceAppState extends ConsumerState { @override void initState() { super.initState(); - Devfest2024Router.instance.initialiseRouter(ref); + + Future.microtask(() async { + final [dynamic isFirstLaunch, dynamic token] = await Future.wait([ + ConferenceAppStorageService.instance.isFirstLaunch, + ConferenceAppStorageService.instance.userToken, + ]); + + if (isFirstLaunch == true && (token.toString()).isEmpty) { + Devfest2024Router.rootNavigatorKey.currentContext + ?.goNamedAndPopAll(OnboardingHomeScreen.route); + return; + } + }); } void _unfocus() { FocusManager.instance.primaryFocus?.unfocus(); } - // This widget is the root of your application. @override Widget build(BuildContext context) { return GestureDetector( @@ -33,9 +46,11 @@ class _ConferenceAppState extends ConsumerState { designSize: designSize, minTextAdapt: true, builder: (_, child) { - return MaterialApp.router( + return MaterialApp( title: 'Devfest24 Conference App', - routerConfig: Devfest2024Router.instance.router, + navigatorKey: Devfest2024Router.rootNavigatorKey, + initialRoute: Devfest2024Router.initialRoute, + onGenerateRoute: Devfest2024Router.instance.onGenerateRoutes, builder: (context, child) => AccessibilityTools( minimumTapAreas: const MinimumTapAreas(mobile: 30, desktop: 44), checkFontOverflows: true, diff --git a/packages/conferenceapp/lib/src/features/dashboard/application/user/view_model.dart b/packages/conferenceapp/lib/src/features/dashboard/application/user/view_model.dart index 24657f3..5a075ce 100644 --- a/packages/conferenceapp/lib/src/features/dashboard/application/user/view_model.dart +++ b/packages/conferenceapp/lib/src/features/dashboard/application/user/view_model.dart @@ -30,6 +30,6 @@ final class UserViewModel extends AutoDisposeNotifier { (right) => state.copyWith(uiState: UiState.success, user: right), ), ); - }); + }, displayError: false); } } diff --git a/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart b/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart index 9c9a96d..2079223 100644 --- a/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart +++ b/packages/conferenceapp/lib/src/features/dashboard/presentation/screens/dashboard.dart @@ -10,6 +10,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../../shared/shared.dart'; class DashboardScreen extends StatelessWidget { + static const route = '/home'; + const DashboardScreen({super.key}); @override @@ -58,6 +60,7 @@ class _ViewState extends ConsumerState<_View> { ref.read(speakersViewModelNotifier.notifier).fetchSpeakers(), ref.read(agendasViewModelNotifier.notifier).fetchAgenda(), ]); + ConferenceAppStorageService.instance.setIsFirstLaunch(false); }); } diff --git a/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart index 8b0851a..070840a 100644 --- a/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/home/presentation/screens/home.dart @@ -1,3 +1,5 @@ +// ignore_for_file: depend_on_referenced_packages + import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; import 'package:devfest24/src/features/dashboard/application/application.dart'; diff --git a/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart index 949baf8..52bb488 100644 --- a/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart @@ -1,13 +1,13 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; -import 'package:devfest24/src/features/more/presentation/widgets/widgets.dart'; import 'package:devfest24/src/routing/routing.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; import '../../../dashboard/application/application.dart'; +import '../../../onboarding/presentation/presentation.dart'; +import '../presentation.dart'; class MoreHomeScreen extends ConsumerWidget { const MoreHomeScreen({super.key}); @@ -30,7 +30,8 @@ class MoreHomeScreen extends ConsumerWidget { else SignedOutUserHeaderTile( signInOnTap: () { - context.goNamed(Devfest2024Routes.onboardingLogin.name); + context.goNamedAndPopAll(OnboardingLoginScreen.route); + ConferenceAppStorageService.instance.setIsFirstLaunch(true); }, ), MoreSection( @@ -43,7 +44,7 @@ class MoreHomeScreen extends ConsumerWidget { size: 22.r, ), onTap: () { - context.goNamed(Devfest2024Routes.profile.name); + context.goNamed(ProfileScreen.route); }, ), MoreButton( @@ -53,7 +54,7 @@ class MoreHomeScreen extends ConsumerWidget { size: 22.r, ), onTap: () { - context.goNamed(Devfest2024Routes.myQrCode.name); + context.goNamed(MyQrCodeScreen.route); }, ), MoreButton( @@ -71,7 +72,7 @@ class MoreHomeScreen extends ConsumerWidget { size: 22.r, ), onTap: () { - context.goNamed(Devfest2024Routes.venueMap.name); + context.goNamed(VenueMapScreen.route); }, ), ], diff --git a/packages/conferenceapp/lib/src/features/more/presentation/screens/my_qr_code.dart b/packages/conferenceapp/lib/src/features/more/presentation/screens/my_qr_code.dart index 4224b29..bd79aae 100644 --- a/packages/conferenceapp/lib/src/features/more/presentation/screens/my_qr_code.dart +++ b/packages/conferenceapp/lib/src/features/more/presentation/screens/my_qr_code.dart @@ -1,21 +1,21 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; import 'package:devfest24/src/features/dashboard/application/application.dart'; +import 'package:devfest24/src/routing/routing.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; class MyQrCodeScreen extends StatelessWidget { + static const route = '/more/my-qr-code'; + const MyQrCodeScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - leading: GoBackButton( - onTap: context.pop, - ), + leading: GoBackButton(onTap: context.pop), leadingWidth: 120.w, ), body: Padding( @@ -43,10 +43,18 @@ class MyQrCodeScreen extends StatelessWidget { ), const Spacer(), Consumer( - builder: (context, ref, child) => QrImageView( + builder: (context, ref, child) { + if (ref + .watch(userViewModelNotifier.select((vm) => vm.user.id)) + .isEmpty) { + return const SizedBox.shrink(); + } + return QrImageView( data: ref .watch(userViewModelNotifier.select((vm) => vm.user.id)), - size: 296.w), + size: 296.w, + ); + }, ), const Spacer(flex: 3), ], diff --git a/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart b/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart index fde14f6..e5e9eb1 100644 --- a/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart +++ b/packages/conferenceapp/lib/src/features/more/presentation/screens/profile.dart @@ -2,13 +2,15 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; import '../../../../routing/routing.dart'; import '../../../dashboard/application/application.dart'; +import '../../../onboarding/presentation/presentation.dart'; import '../widgets/widgets.dart'; import 'package:flutter/material.dart'; class ProfileScreen extends ConsumerWidget { + static const route = '/more/profile'; + const ProfileScreen({super.key}); @override @@ -37,7 +39,8 @@ class ProfileScreen extends ConsumerWidget { else SignedOutUserHeaderTile( signInOnTap: () { - context.goNamed(Devfest2024Routes.onboardingLogin.name); + context.goNamedAndPopAll(OnboardingLoginScreen.route); + ConferenceAppStorageService.instance.setIsFirstLaunch(true); }, ), Expanded( diff --git a/packages/conferenceapp/lib/src/features/more/presentation/screens/venue_map.dart b/packages/conferenceapp/lib/src/features/more/presentation/screens/venue_map.dart index a9c4d58..058f332 100644 --- a/packages/conferenceapp/lib/src/features/more/presentation/screens/venue_map.dart +++ b/packages/conferenceapp/lib/src/features/more/presentation/screens/venue_map.dart @@ -2,9 +2,9 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; import 'package:devfest24/src/features/more/presentation/map/map.dart'; import 'package:devfest24/src/features/more/presentation/widgets/map.dart'; +import 'package:devfest24/src/routing/routing.dart'; import 'package:flutter/material.dart' hide Action; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; import '../../../../shared/shared.dart'; import '../widgets/map_layout.dart'; @@ -22,6 +22,8 @@ final showBlocksProvider = StateProvider.autoDispose((ref) { }); class VenueMapScreen extends ConsumerStatefulWidget { + static const route = '/home/venue-map'; + const VenueMapScreen({super.key}); @override diff --git a/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/home.dart index 5c47812..6d6b5c1 100644 --- a/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/home.dart @@ -3,62 +3,68 @@ import 'package:cave/constants.dart'; import 'package:devfest24/src/routing/routing.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; + +import 'login.dart'; class OnboardingHomeScreen extends StatelessWidget { + static const route = '/onboarding'; + const OnboardingHomeScreen({super.key}); @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - leadingWidth: 100.w, - leading: Row( - children: [ - Padding( - padding: EdgeInsets.only(left: Constants.horizontalMargin.w), - child: GdgLogo.normal(), - ), - ], + return PopScope( + canPop: false, + child: Scaffold( + appBar: AppBar( + leadingWidth: 100.w, + leading: Row( + children: [ + Padding( + padding: EdgeInsets.only(left: Constants.horizontalMargin.w), + child: GdgLogo.normal(), + ), + ], + ), ), - ), - body: SafeArea( - child: Stack( - children: [ - Padding( - padding: EdgeInsets.symmetric( - horizontal: Constants.horizontalMargin.w), - child: Column( - children: [ - const HeaderText( - title: Text( - 'DevFest Lagos like you have never seen it before'), - subtitle: Text( - 'We said we will see you again next year, here we are, we have missed you and prepared amazing things for you ๐Ÿฅบ', + body: SafeArea( + child: Stack( + children: [ + Padding( + padding: EdgeInsets.symmetric( + horizontal: Constants.horizontalMargin.w), + child: Column( + children: [ + const HeaderText( + title: Text( + 'DevFest Lagos like you have never seen it before'), + subtitle: Text( + 'We said we will see you again next year, here we are, we have missed you and prepared amazing things for you ๐Ÿฅบ', + ), ), - ), - SizedBox(height: (Constants.largeVerticalGutter * 3).h), - DevfestFilledButton( - onPressed: () { - context.goNamed(Devfest2024Routes.onboardingLogin.name); - }, - title: const Text('Let\'s Get This Bread Quickly'), - ) - ], + SizedBox(height: (Constants.largeVerticalGutter * 3).h), + DevfestFilledButton( + onPressed: () { + context.goNamedAndPopAll(OnboardingLoginScreen.route); + }, + title: const Text('Let\'s Get This Bread Quickly'), + ) + ], + ), ), - ), - Positioned( - bottom: 0, - left: 0, - right: 0, - child: SvgPicture.asset( - 'images/conference_onboarding.svg', - package: 'cave', - semanticsLabel: 'Onboarding Image', - fit: BoxFit.contain, + Positioned( + bottom: 0, + left: 0, + right: 0, + child: SvgPicture.asset( + 'images/conference_onboarding.svg', + package: 'cave', + semanticsLabel: 'Onboarding Image', + fit: BoxFit.contain, + ), ), - ), - ], + ], + ), ), ), ); diff --git a/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/login.dart b/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/login.dart index ddeee33..060f74f 100644 --- a/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/login.dart +++ b/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/login.dart @@ -5,12 +5,15 @@ import 'package:devfest24/src/routing/routing.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; + +import '../../../dashboard/presentation/screens/dashboard.dart'; final _emailRegexp = RegExp( r'^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$'); class OnboardingLoginScreen extends ConsumerStatefulWidget { + static const route = '/onboarding/login'; + const OnboardingLoginScreen({super.key}); @override @@ -26,7 +29,7 @@ class _OnboardingLoginScreenState extends ConsumerState { super.initState(); ref.listenManual(sessionSignInVMNotifier, (previous, next) { if (next.uiState.isSuccess) { - context.goNamed(Devfest2024Routes.dashboard.name); + context.goNamedAndPopAll(DashboardScreen.route); return; } }); @@ -170,7 +173,7 @@ class _OnboardingLoginScreenState extends ConsumerState { titleStyle: TextStyle( color: DevfestColors.grey10.possibleDarkVariant), onPressed: () { - context.goNamed(Devfest2024Routes.dashboard.name); + context.goNamedAndPopAll(DashboardScreen.route); }, ), ], diff --git a/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/signature.dart b/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/signature.dart index 9af1ec5..a5c082f 100644 --- a/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/signature.dart +++ b/packages/conferenceapp/lib/src/features/onboarding/presentation/screens/signature.dart @@ -6,12 +6,14 @@ import 'package:devfest24/src/features/onboarding/presentation/widgets/widgets.d import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -import 'package:go_router/go_router.dart'; import '../../../../routing/routing.dart'; +import '../../../dashboard/presentation/screens/dashboard.dart'; import '../widgets/path_to_svg_parser.dart'; class OnboardingSignatureScreen extends StatefulWidget { + static const route = '/onboarding/login/signature'; + const OnboardingSignatureScreen({super.key}); @override @@ -47,7 +49,7 @@ class _OnboardingSignatureScreenState extends State { color: DevfestColors.grey50.possibleDarkVariant, ).semi, onPressed: () { - context.goNamed(Devfest2024Routes.dashboard.name); + context.goNamedAndPopAll(DashboardScreen.route); }, ), ), diff --git a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart index a775c6a..9fb980b 100644 --- a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart @@ -5,7 +5,6 @@ import 'package:devfest24/src/routing/routing.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; import '../../../dashboard/application/application.dart'; @@ -81,7 +80,7 @@ class _ScheduleHomeScreenState extends ConsumerState { ? ScheduleTileType.breakout : ScheduleTileType.session, onTap: () { - context.goNamed(Devfest2024Routes.scheduleDetails.name); + context.goNamed(ScheduleDetailsScreen.route); }, ); }, diff --git a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart index e1c6bf9..977b773 100644 --- a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart +++ b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart @@ -1,11 +1,13 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; import 'package:cave/ui_utils/container_properties.dart'; +import 'package:devfest24/src/routing/routing.dart'; import 'package:devfest24/src/shared/widgets/speaker_talk_info_pill.dart'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; class ScheduleDetailsScreen extends StatelessWidget { + static const route = '/home/schedule-details'; + const ScheduleDetailsScreen({super.key}); @override diff --git a/packages/conferenceapp/lib/src/features/speakers/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/speakers/presentation/screens/home.dart index 46f0228..90d0299 100644 --- a/packages/conferenceapp/lib/src/features/speakers/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/speakers/presentation/screens/home.dart @@ -5,10 +5,10 @@ import 'package:devfest24/src/features/speakers/presentation/widgets/widgets.dar import 'package:devfest24/src/routing/routing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; import '../../../../shared/shared.dart'; import '../../../dashboard/application/application.dart'; +import 'screens.dart'; class SpeakersHomeScreen extends ConsumerStatefulWidget { const SpeakersHomeScreen({super.key}); @@ -133,8 +133,8 @@ class _SpeakersList extends ConsumerWidget { speaker: speaker, onTap: () { context.goNamed( - Devfest2024Routes.speakerDetails.name, - extra: speaker, + SpeakerDetailsScreen.route, + arguments: speaker, ); }, ); diff --git a/packages/conferenceapp/lib/src/features/speakers/presentation/screens/speaker_details.dart b/packages/conferenceapp/lib/src/features/speakers/presentation/screens/speaker_details.dart index 75c45a8..67526e9 100644 --- a/packages/conferenceapp/lib/src/features/speakers/presentation/screens/speaker_details.dart +++ b/packages/conferenceapp/lib/src/features/speakers/presentation/screens/speaker_details.dart @@ -2,17 +2,18 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; import 'package:cave/ui_utils/container_properties.dart'; import 'package:devfest24/src/features/speakers/presentation/widgets/speaker_social_media.dart'; +import 'package:devfest24/src/routing/routing.dart'; import 'package:devfest24/src/shared/shared.dart'; import 'package:devfest24/src/shared/widgets/speaker_talk_info_pill.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; import 'package:iconoir_flutter/iconoir_flutter.dart' hide Text, List, Key, Radius, Brightness, Map; import '../../../dashboard/model/model.dart'; class SpeakerDetailsScreen extends ConsumerStatefulWidget { + static const route = '/home/speaker-details'; const SpeakerDetailsScreen({super.key, required this.speaker}); final SpeakerDto speaker; diff --git a/packages/conferenceapp/lib/src/routing/extra_codec.dart b/packages/conferenceapp/lib/src/routing/extra_codec.dart deleted file mode 100644 index 8c03cf3..0000000 --- a/packages/conferenceapp/lib/src/routing/extra_codec.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'dart:convert'; - -import '../features/dashboard/model/model.dart'; - -class ConferenceExtraCodec extends Codec { - const ConferenceExtraCodec({ - this.decoder = const _ConferenceExtraDecoder(), - this.encoder = const _ConferenceExtraEncoder(), - }); - - @override - final Converter decoder; - - @override - final Converter encoder; -} - -class _ConferenceExtraDecoder extends Converter { - const _ConferenceExtraDecoder(); - - @override - Object? convert(Object? input) { - if (input == null) { - return null; - } - final List inputAsList = input as List; - return switch (inputAsList[0]) { - 'SpeakerDto' => - SpeakerDto.fromJson(inputAsList[1] as Map), - _ => throw FormatException('Unable to parse input: $input'), - }; - } -} - -class _ConferenceExtraEncoder extends Converter { - const _ConferenceExtraEncoder(); - - @override - Object? convert(Object? input) { - if (input == null) { - return null; - } - - return switch (input) { - SpeakerDto dto => ['SpeakerDto', dto.toJson()], - _ => throw FormatException('Cannot encode type ${input.runtimeType}'), - }; - } -} diff --git a/packages/conferenceapp/lib/src/routing/router.dart b/packages/conferenceapp/lib/src/routing/router.dart index 8cac1bb..50477a2 100644 --- a/packages/conferenceapp/lib/src/routing/router.dart +++ b/packages/conferenceapp/lib/src/routing/router.dart @@ -1,16 +1,11 @@ -import 'package:cave/cave.dart'; import 'package:devfest24/src/features/dashboard/presentation/screens/dashboard.dart'; import 'package:devfest24/src/features/more/presentation/presentation.dart'; import 'package:devfest24/src/features/onboarding/presentation/presentation.dart'; import 'package:devfest24/src/features/schedule/presentation/presentation.dart'; import 'package:devfest24/src/features/speakers/presentation/presentation.dart'; -import 'package:devfest24/src/routing/extra_codec.dart'; import '../features/dashboard/model/model.dart'; -import 'routes.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; class Devfest2024Router { static final rootNavigatorKey = GlobalKey(); @@ -19,77 +14,116 @@ class Devfest2024Router { static final Devfest2024Router instance = Devfest2024Router._(); - void initialiseRouter(WidgetRef ref) { - router = _getRouter(ref); + static String initialRoute = DashboardScreen.route; + + Route onGenerateRoutes(RouteSettings settings) { + return switch (settings.name) { + OnboardingHomeScreen.route => + MaterialPageRoute(builder: (_) => const OnboardingHomeScreen()), + OnboardingLoginScreen.route => + MaterialPageRoute(builder: (_) => const OnboardingLoginScreen()), + OnboardingSignatureScreen.route => + MaterialPageRoute(builder: (_) => const OnboardingSignatureScreen()), + DashboardScreen.route => + MaterialPageRoute(builder: (_) => const DashboardScreen()), + ScheduleDetailsScreen.route => + MaterialPageRoute(builder: (_) => const ScheduleDetailsScreen()), + SpeakerDetailsScreen.route => MaterialPageRoute( + builder: (_) => + SpeakerDetailsScreen(speaker: settings.arguments as SpeakerDto)), + MyQrCodeScreen.route => + MaterialPageRoute(builder: (_) => const MyQrCodeScreen()), + ProfileScreen.route => + MaterialPageRoute(builder: (_) => const ProfileScreen()), + VenueMapScreen.route => + MaterialPageRoute(builder: (_) => const VenueMapScreen()), + _ => MaterialPageRoute( + builder: (_) => Scaffold( + body: Center( + child: Text('No route defined for ${settings.name}'), + ), + ), + ), + }; } - late GoRouter router; +// GoRouter _getRouter(WidgetRef ref) { +// return GoRouter( +// navigatorKey: rootNavigatorKey, +// initialLocation: '/', +// extraCodec: const ConferenceExtraCodec(), +// redirect: (context, state) async { +// final token = await ConferenceAppStorageService.instance.userToken; +// if (token.isEmpty) { +// return '/${Devfest2024Routes.onboardingHome.path}'; +// } +// +// return null; +// }, +// routes: [ +// GoRoute( +// path: '/${Devfest2024Routes.onboardingHome.path}', +// name: Devfest2024Routes.onboardingHome.name, +// builder: (context, state) => const OnboardingHomeScreen(), +// routes: [ +// GoRoute( +// path: Devfest2024Routes.onboardingLogin.path, +// name: Devfest2024Routes.onboardingLogin.name, +// builder: (context, state) => const OnboardingLoginScreen(), +// ), +// GoRoute( +// path: Devfest2024Routes.onboardingSignature.path, +// name: Devfest2024Routes.onboardingSignature.name, +// builder: (context, state) => const OnboardingSignatureScreen(), +// ), +// ], +// ), +// GoRoute( +// path: '/', +// name: Devfest2024Routes.dashboard.name, +// builder: (context, state) => const DashboardScreen(), +// routes: [ +// GoRoute( +// path: Devfest2024Routes.speakerDetails.path, +// name: Devfest2024Routes.speakerDetails.name, +// builder: (context, state) => SpeakerDetailsScreen( +// speaker: state.extra as SpeakerDto, +// ), +// ), +// GoRoute( +// path: Devfest2024Routes.scheduleDetails.path, +// name: Devfest2024Routes.scheduleDetails.name, +// builder: (context, state) => const ScheduleDetailsScreen(), +// ), +// GoRoute( +// path: Devfest2024Routes.profile.path, +// name: Devfest2024Routes.profile.name, +// builder: (context, state) => const ProfileScreen(), +// ), +// GoRoute( +// path: Devfest2024Routes.myQrCode.path, +// name: Devfest2024Routes.myQrCode.name, +// builder: (context, state) => const MyQrCodeScreen(), +// ), +// GoRoute( +// path: Devfest2024Routes.venueMap.path, +// name: Devfest2024Routes.venueMap.name, +// builder: (context, state) => const VenueMapScreen(), +// ), +// ], +// ), +// ], +// ); +// } +} - GoRouter _getRouter(WidgetRef ref) { - return GoRouter( - navigatorKey: rootNavigatorKey, - initialLocation: '/', - extraCodec: const ConferenceExtraCodec(), - redirect: (context, state) async { - final token = await ConferenceAppStorageService.instance.userToken; - if (token.isEmpty) { - return '/${Devfest2024Routes.onboardingHome.path}'; - } +extension BuildContextX on BuildContext { + void pop([T? result]) => Navigator.of(this).pop(result); - return null; - }, - routes: [ - GoRoute( - path: '/${Devfest2024Routes.onboardingHome.path}', - name: Devfest2024Routes.onboardingHome.name, - builder: (context, state) => const OnboardingHomeScreen(), - routes: [ - GoRoute( - path: Devfest2024Routes.onboardingLogin.path, - name: Devfest2024Routes.onboardingLogin.name, - builder: (context, state) => const OnboardingLoginScreen(), - ), - GoRoute( - path: Devfest2024Routes.onboardingSignature.path, - name: Devfest2024Routes.onboardingSignature.name, - builder: (context, state) => const OnboardingSignatureScreen(), - ), - ], - ), - GoRoute( - path: '/', - name: Devfest2024Routes.dashboard.name, - builder: (context, state) => const DashboardScreen(), - routes: [ - GoRoute( - path: Devfest2024Routes.speakerDetails.path, - name: Devfest2024Routes.speakerDetails.name, - builder: (context, state) => SpeakerDetailsScreen( - speaker: state.extra as SpeakerDto, - ), - ), - GoRoute( - path: Devfest2024Routes.scheduleDetails.path, - name: Devfest2024Routes.scheduleDetails.name, - builder: (context, state) => const ScheduleDetailsScreen(), - ), - GoRoute( - path: Devfest2024Routes.profile.path, - name: Devfest2024Routes.profile.name, - builder: (context, state) => const ProfileScreen(), - ), - GoRoute( - path: Devfest2024Routes.myQrCode.path, - name: Devfest2024Routes.myQrCode.name, - builder: (context, state) => const MyQrCodeScreen(), - ), - GoRoute( - path: Devfest2024Routes.venueMap.path, - name: Devfest2024Routes.venueMap.name, - builder: (context, state) => const VenueMapScreen(), - ), - ], - ), - ]); - } + Future goNamed(String routeName, {Object? arguments}) => + Navigator.of(this).pushNamed(routeName, arguments: arguments); + + Future goNamedAndPopAll(String routeName, {Object? arguments}) => + Navigator.of(this).pushNamedAndRemoveUntil(routeName, (route) => false, + arguments: arguments); } diff --git a/packages/conferenceapp/lib/src/routing/routes.dart b/packages/conferenceapp/lib/src/routing/routes.dart deleted file mode 100644 index 7a8cd6d..0000000 --- a/packages/conferenceapp/lib/src/routing/routes.dart +++ /dev/null @@ -1,15 +0,0 @@ -enum Devfest2024Routes { - onboardingHome('onboarding'), - onboardingLogin('log-in'), - onboardingSignature('signature'), - dashboard(''), - speakerDetails('speaker-details'), - scheduleDetails('schedule-details'), - profile('profile'), - myQrCode('qr-code'), - venueMap('map'); - - const Devfest2024Routes(this.path); - - final String path; -} diff --git a/packages/conferenceapp/lib/src/routing/routing.dart b/packages/conferenceapp/lib/src/routing/routing.dart index 8d1b6be..58b1402 100644 --- a/packages/conferenceapp/lib/src/routing/routing.dart +++ b/packages/conferenceapp/lib/src/routing/routing.dart @@ -1,3 +1,2 @@ //GENERATED BARREL FILE export 'router.dart'; -export 'routes.dart'; diff --git a/packages/conferenceapp/lib/src/shared/ui_model/ui_state_model.dart b/packages/conferenceapp/lib/src/shared/ui_model/ui_state_model.dart index e990237..3cca04e 100644 --- a/packages/conferenceapp/lib/src/shared/ui_model/ui_state_model.dart +++ b/packages/conferenceapp/lib/src/shared/ui_model/ui_state_model.dart @@ -3,7 +3,6 @@ import 'package:cave/cave.dart'; import 'package:devfest24/src/routing/routing.dart'; import 'package:equatable/equatable.dart'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; part 'ui_state_model_mutex.dart'; @@ -80,10 +79,6 @@ extension ViewModelX on T { ); ScaffoldMessenger.of(context).showSnackBar(snackbar); - - if (error is UnauthorizedUserException) { - context.go(Devfest2024Routes.onboardingHome.name); - } } } diff --git a/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart b/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart index 6dd4ff2..10c16f8 100644 --- a/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart +++ b/packages/conferenceapp/lib/src/shared/widgets/check_in_button.dart @@ -1,7 +1,8 @@ import 'package:cave/cave.dart'; import 'package:devfest24/src/routing/routing.dart'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; + +import '../../features/onboarding/presentation/presentation.dart'; class CheckInButton extends StatelessWidget { const CheckInButton({ @@ -22,7 +23,8 @@ class CheckInButton extends StatelessWidget { child: isLoggedIn ? _CheckInButton(onCheckInTap) : _LoginCheckInButton(() { - context.goNamed(Devfest2024Routes.onboardingLogin.name); + context.goNamedAndPopAll(OnboardingLoginScreen.route); + ConferenceAppStorageService.instance.setIsFirstLaunch(true); }), ); } diff --git a/packages/conferenceapp/pubspec.lock b/packages/conferenceapp/pubspec.lock index 7ab6dc4..4f3540e 100644 --- a/packages/conferenceapp/pubspec.lock +++ b/packages/conferenceapp/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: "direct main" description: name: accessibility_tools - sha256: "7c0b5ac466ea8b971c1b081f3ade0979e6563e8926da62c3b90def78c44dd96b" + sha256: ae082866ddc7d4b06d7344f20f551d71302c80070d1e6c5f112f1d09b98de95c url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" args: dependency: transitive description: @@ -327,14 +327,6 @@ packages: description: flutter source: sdk version: "0.0.0" - go_router: - dependency: "direct main" - description: - name: go_router - sha256: "6f1b756f6e863259a99135ff3c95026c3cdca17d10ebef2bba2261a25ddc8bbc" - url: "https://pub.dev" - source: hosted - version: "14.3.0" http: dependency: transitive description: @@ -407,14 +399,6 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0" - logging: - dependency: transitive - description: - name: logging - sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" - url: "https://pub.dev" - source: hosted - version: "1.2.0" matcher: dependency: transitive description: diff --git a/packages/conferenceapp/pubspec.yaml b/packages/conferenceapp/pubspec.yaml index 72f80ed..e25cd73 100644 --- a/packages/conferenceapp/pubspec.yaml +++ b/packages/conferenceapp/pubspec.yaml @@ -10,7 +10,7 @@ environment: sdk: '>=3.4.4 <4.0.0' dependencies: - accessibility_tools: ^2.2.2 + accessibility_tools: ^2.2.3 cave: path: ../cave @@ -19,7 +19,6 @@ dependencies: flutter: sdk: flutter flutter_riverpod: ^2.5.1 - go_router: ^14.3.0 intl: ^0.19.0 mesh: ^0.4.1 package_info_plus: ^8.0.2 From 7c2b231cef4e7efa4d2c3289837b9161baa5c236 Mon Sep 17 00:00:00 2001 From: Sebastine Odeh Date: Sat, 26 Oct 2024 08:55:07 +0100 Subject: [PATCH 6/8] linting --- .../lib/src/features/more/presentation/screens/home.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart index 52bb488..7950dc2 100644 --- a/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/more/presentation/screens/home.dart @@ -31,7 +31,8 @@ class MoreHomeScreen extends ConsumerWidget { SignedOutUserHeaderTile( signInOnTap: () { context.goNamedAndPopAll(OnboardingLoginScreen.route); - ConferenceAppStorageService.instance.setIsFirstLaunch(true); + ConferenceAppStorageService.instance + .setIsFirstLaunch(true); }, ), MoreSection( From 22f15d9e44568e2c01ecbdcc663c0acb514bd2fd Mon Sep 17 00:00:00 2001 From: Iyinoluwa Date: Mon, 28 Oct 2024 16:05:49 +0000 Subject: [PATCH 7/8] added session details --- .../features/schedule/presentation/screens/home.dart | 2 +- .../presentation/screens/schedule_details.dart | 12 ++++++++---- packages/conferenceapp/lib/src/routing/router.dart | 2 +- .../conferenceapp/lib/src/shared/extensions.dart | 9 +++++++++ 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart index 9fb980b..4bda525 100644 --- a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart @@ -80,7 +80,7 @@ class _ScheduleHomeScreenState extends ConsumerState { ? ScheduleTileType.breakout : ScheduleTileType.session, onTap: () { - context.goNamed(ScheduleDetailsScreen.route); + context.goNamed(ScheduleDetailsScreen.route,arguments: session); }, ); }, diff --git a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart index 977b773..45fd44a 100644 --- a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart +++ b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart @@ -1,14 +1,18 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; import 'package:cave/ui_utils/container_properties.dart'; +import 'package:devfest24/src/features/dashboard/application/agenda/view_model.dart'; +import 'package:devfest24/src/features/dashboard/model/model.dart'; import 'package:devfest24/src/routing/routing.dart'; +import 'package:devfest24/src/shared/shared.dart'; import 'package:devfest24/src/shared/widgets/speaker_talk_info_pill.dart'; import 'package:flutter/material.dart'; class ScheduleDetailsScreen extends StatelessWidget { static const route = '/home/schedule-details'; - const ScheduleDetailsScreen({super.key}); + const ScheduleDetailsScreen({super.key,required this.session}); + final SessionDto session; @override Widget build(BuildContext context) { @@ -25,7 +29,7 @@ class ScheduleDetailsScreen extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '๐Ÿ˜˜ Women Tech Makers Breakfast', + session.title, style: DevfestTheme.of(context).textTheme?.titleTitle2Semibold?.semi, ), @@ -51,7 +55,7 @@ class ScheduleDetailsScreen extends StatelessWidget { ), Constants.horizontalGutter.horizontalSpace, Text( - 'Femi Falana', + session.speakers.getNames, style: DevfestTheme.of(context).textTheme?.bodyBody1Medium?.semi, ), @@ -82,7 +86,7 @@ class ScheduleDetailsScreen extends StatelessWidget { ), Constants.verticalGutter.verticalSpace, Text( - 'Wake up to reality! Nothing ever goes as planned in this accursed world. The longer you live, the more you realize that the only things that truly exist in this reality are merely pain, suffering and futility. Listen, everywhere you look in this world, wherever there is light, there will always be shadows to be found as well. As long as there is a concept of victors, the vanquished will also exist. The selfish intent of wanting to preserve peace, initiates war and hatred is born in order to protect love. There are nexuses causal relationships that cannot be separated.', + session.descrption, style: DevfestTheme.of(context).textTheme?.bodyBody2Medium?.semi, ), ], diff --git a/packages/conferenceapp/lib/src/routing/router.dart b/packages/conferenceapp/lib/src/routing/router.dart index 50477a2..63cb67e 100644 --- a/packages/conferenceapp/lib/src/routing/router.dart +++ b/packages/conferenceapp/lib/src/routing/router.dart @@ -27,7 +27,7 @@ class Devfest2024Router { DashboardScreen.route => MaterialPageRoute(builder: (_) => const DashboardScreen()), ScheduleDetailsScreen.route => - MaterialPageRoute(builder: (_) => const ScheduleDetailsScreen()), + MaterialPageRoute(builder: (_) => ScheduleDetailsScreen(session:settings.arguments as SessionDto,)), SpeakerDetailsScreen.route => MaterialPageRoute( builder: (_) => SpeakerDetailsScreen(speaker: settings.arguments as SpeakerDto)), diff --git a/packages/conferenceapp/lib/src/shared/extensions.dart b/packages/conferenceapp/lib/src/shared/extensions.dart index 48485c5..986b79e 100644 --- a/packages/conferenceapp/lib/src/shared/extensions.dart +++ b/packages/conferenceapp/lib/src/shared/extensions.dart @@ -1,4 +1,5 @@ import 'package:cave/cave.dart'; +import 'package:devfest24/src/features/dashboard/model/model.dart'; import 'package:devfest24/src/routing/routing.dart'; import 'package:flutter/material.dart'; @@ -36,3 +37,11 @@ extension ListX on List { } } } + +extension SpeakerNames on List { + String get getNames => getSpeakerNames(this); + String getSpeakerNames(List speakers) { + final names = speakers.map((speaker) => speaker.fullname).toList(); + return names.join(', '); + } +} \ No newline at end of file From 11f54c5cebc1b4a47f4fa9546704b3a591104e70 Mon Sep 17 00:00:00 2001 From: Iyinoluwa Date: Mon, 28 Oct 2024 16:12:47 +0000 Subject: [PATCH 8/8] added session details --- packages/cave/lib/cave.dart | 2 +- .../src/features/schedule/presentation/screens/home.dart | 3 ++- .../schedule/presentation/screens/schedule_details.dart | 3 +-- packages/conferenceapp/lib/src/routing/router.dart | 6 ++++-- packages/conferenceapp/lib/src/shared/extensions.dart | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/cave/lib/cave.dart b/packages/cave/lib/cave.dart index f815150..281cd1b 100644 --- a/packages/cave/lib/cave.dart +++ b/packages/cave/lib/cave.dart @@ -1,4 +1,4 @@ -library cave; +library; export 'themes/themes.dart'; export 'widgets/widgets.dart'; diff --git a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart index 4bda525..c1208f8 100644 --- a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart +++ b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/home.dart @@ -80,7 +80,8 @@ class _ScheduleHomeScreenState extends ConsumerState { ? ScheduleTileType.breakout : ScheduleTileType.session, onTap: () { - context.goNamed(ScheduleDetailsScreen.route,arguments: session); + context.goNamed(ScheduleDetailsScreen.route, + arguments: session); }, ); }, diff --git a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart index 45fd44a..826d40d 100644 --- a/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart +++ b/packages/conferenceapp/lib/src/features/schedule/presentation/screens/schedule_details.dart @@ -1,7 +1,6 @@ import 'package:cave/cave.dart'; import 'package:cave/constants.dart'; import 'package:cave/ui_utils/container_properties.dart'; -import 'package:devfest24/src/features/dashboard/application/agenda/view_model.dart'; import 'package:devfest24/src/features/dashboard/model/model.dart'; import 'package:devfest24/src/routing/routing.dart'; import 'package:devfest24/src/shared/shared.dart'; @@ -11,7 +10,7 @@ import 'package:flutter/material.dart'; class ScheduleDetailsScreen extends StatelessWidget { static const route = '/home/schedule-details'; - const ScheduleDetailsScreen({super.key,required this.session}); + const ScheduleDetailsScreen({super.key, required this.session}); final SessionDto session; @override diff --git a/packages/conferenceapp/lib/src/routing/router.dart b/packages/conferenceapp/lib/src/routing/router.dart index 63cb67e..b1d8287 100644 --- a/packages/conferenceapp/lib/src/routing/router.dart +++ b/packages/conferenceapp/lib/src/routing/router.dart @@ -26,8 +26,10 @@ class Devfest2024Router { MaterialPageRoute(builder: (_) => const OnboardingSignatureScreen()), DashboardScreen.route => MaterialPageRoute(builder: (_) => const DashboardScreen()), - ScheduleDetailsScreen.route => - MaterialPageRoute(builder: (_) => ScheduleDetailsScreen(session:settings.arguments as SessionDto,)), + ScheduleDetailsScreen.route => MaterialPageRoute( + builder: (_) => ScheduleDetailsScreen( + session: settings.arguments as SessionDto, + )), SpeakerDetailsScreen.route => MaterialPageRoute( builder: (_) => SpeakerDetailsScreen(speaker: settings.arguments as SpeakerDto)), diff --git a/packages/conferenceapp/lib/src/shared/extensions.dart b/packages/conferenceapp/lib/src/shared/extensions.dart index 986b79e..69b9c70 100644 --- a/packages/conferenceapp/lib/src/shared/extensions.dart +++ b/packages/conferenceapp/lib/src/shared/extensions.dart @@ -44,4 +44,4 @@ extension SpeakerNames on List { final names = speakers.map((speaker) => speaker.fullname).toList(); return names.join(', '); } -} \ No newline at end of file +}