From 9b78ae40d048d63cd622be90d1164699e3af597b Mon Sep 17 00:00:00 2001 From: Michael Thomas Date: Wed, 7 Sep 2022 13:34:03 -0400 Subject: [PATCH] Pull-down student id gesture, salmon bar navigation, global state --- ios/Podfile.lock | 12 ++ lib/main.dart | 9 +- lib/src/layouts/main/index.dart | 55 ++++--- lib/src/routes/index.dart | 20 ++- lib/src/routes/index.gr.dart | 143 ++++++++++-------- lib/src/screens/home/index.dart | 121 +++++++++++---- lib/src/screens/student_id/index.dart | 140 +++++++++++++---- lib/src/store/index.dart | 33 ++++ lib/src/utils/hero_empty_router_page.dart | 14 ++ lib/src/widgets/events/events_list.dart | 100 ++++++------ .../home/restaurants/restaurants_list.dart | 82 +++++----- pubspec.lock | 28 ++++ pubspec.yaml | 3 + 13 files changed, 516 insertions(+), 244 deletions(-) create mode 100644 lib/src/store/index.dart create mode 100644 lib/src/utils/hero_empty_router_page.dart diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 8ee2123..5b2d05b 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,20 +1,32 @@ PODS: - Flutter (1.0.0) + - flutter_compass (0.0.1): + - Flutter + - geolocator_apple (1.2.0): + - Flutter - path_provider_ios (0.0.1): - Flutter DEPENDENCIES: - Flutter (from `Flutter`) + - flutter_compass (from `.symlinks/plugins/flutter_compass/ios`) + - geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`) - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) EXTERNAL SOURCES: Flutter: :path: Flutter + flutter_compass: + :path: ".symlinks/plugins/flutter_compass/ios" + geolocator_apple: + :path: ".symlinks/plugins/geolocator_apple/ios" path_provider_ios: :path: ".symlinks/plugins/path_provider_ios/ios" SPEC CHECKSUMS: Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a + flutter_compass: cbbd285cea1584c7ac9c4e0c3e1f17cbea55e855 + geolocator_apple: cc556e6844d508c95df1e87e3ea6fa4e58c50401 path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c diff --git a/lib/main.dart b/lib/main.dart index 93553aa..35b9680 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,13 @@ import 'package:flutter/material.dart'; import 'package:furman_now/src/app.dart'; +import 'package:furman_now/src/store/index.dart'; +import 'package:provider/provider.dart'; void main() { - runApp(App()); + runApp( + ChangeNotifierProvider( + create: (context) => AppState(), + child: App(), + ), + ); } diff --git a/lib/src/layouts/main/index.dart b/lib/src/layouts/main/index.dart index 466ce17..09357c0 100644 --- a/lib/src/layouts/main/index.dart +++ b/lib/src/layouts/main/index.dart @@ -1,6 +1,8 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_remix/flutter_remix.dart'; import 'package:furman_now/src/routes/index.gr.dart'; +import 'package:salomon_bottom_bar/salomon_bottom_bar.dart'; class MainLayout extends StatefulWidget { const MainLayout({ @@ -34,7 +36,9 @@ class _MainLayoutState extends State { Widget build(BuildContext context) { return AutoTabsScaffold( routes: const [ - HomeRoute(), + HomePageRouter(children: [ + HomeRoute(), + ]), MapRoute(), EventsRoute(), InfoRoute(), @@ -59,29 +63,32 @@ class _MainLayoutState extends State { } } }, - child: BottomNavigationBar( - items: const [ - BottomNavigationBarItem( - icon: Icon(Icons.home), - label: 'Home', - ), - BottomNavigationBarItem( - icon: Icon(Icons.map), - label: 'Map', - ), - BottomNavigationBarItem( - icon: Icon(Icons.calendar_month), - label: 'Events', - ), - BottomNavigationBarItem( - icon: Icon(Icons.info_outline), - label: 'Info', - ), - ], - currentIndex: tabsRouter.activeIndex, - selectedItemColor: Theme.of(context).primaryColor, - unselectedItemColor: Colors.grey[600], - onTap: tabsRouter.setActiveIndex, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 5, horizontal: 20), + child: SalomonBottomBar( + items: [ + SalomonBottomBarItem( + icon: const Icon(FlutterRemix.home_line), + title: const Text('Home'), + ), + SalomonBottomBarItem( + icon: const Icon(FlutterRemix.map_2_line), + title: const Text('Map'), + ), + SalomonBottomBarItem( + icon: const Icon(FlutterRemix.calendar_line), + title: const Text('Events'), + ), + SalomonBottomBarItem( + icon: const Icon(FlutterRemix.information_line), + title: const Text('Info'), + ), + ], + currentIndex: tabsRouter.activeIndex, + selectedItemColor: Theme.of(context).primaryColor, + unselectedItemColor: Colors.grey[600], + onTap: tabsRouter.setActiveIndex, + ), ), ); }, diff --git a/lib/src/routes/index.dart b/lib/src/routes/index.dart index 9278cba..4db6e64 100644 --- a/lib/src/routes/index.dart +++ b/lib/src/routes/index.dart @@ -4,6 +4,7 @@ import 'package:furman_now/src/screens/home/index.dart'; import 'package:furman_now/src/screens/info/index.dart'; import 'package:furman_now/src/screens/map/index.dart'; import 'package:furman_now/src/screens/student_id/index.dart'; +import 'package:furman_now/src/utils/hero_empty_router_page.dart'; import '../layouts/main/index.dart'; @@ -11,17 +12,22 @@ import '../layouts/main/index.dart'; replaceInRouteName: 'Screen,Route', routes: [ AutoRoute(path: "/", page: MainLayout, children: [ - AutoRoute(path: "home", page: HomeScreen), + AutoRoute(path: "home", name: "HomePageRouter", page: HeroEmptyRouterPage, children: [ + CustomRoute( + path: "", + page: HomeScreen, + transitionsBuilder: TransitionsBuilders.noTransition, + ), + CustomRoute( + path: "student-id", + page: StudentIdScreen, + transitionsBuilder: TransitionsBuilders.noTransition, + ), + ]), AutoRoute(path: "map", page: MapScreen), AutoRoute(path: "events", page: EventsScreen), AutoRoute(path: "info", page: InfoScreen), ]), - CustomRoute( - path: "/student-id", - page: StudentIdScreen, - transitionsBuilder: TransitionsBuilders.slideTop, - durationInMilliseconds: 200, - ), ], ) class $AppRouter {} \ No newline at end of file diff --git a/lib/src/routes/index.gr.dart b/lib/src/routes/index.gr.dart index b7140df..fff86f4 100644 --- a/lib/src/routes/index.gr.dart +++ b/lib/src/routes/index.gr.dart @@ -11,112 +11,135 @@ // ignore_for_file: type=lint // ignore_for_file: no_leading_underscores_for_library_prefixes -import 'package:auto_route/auto_route.dart' as _i7; -import 'package:flutter/material.dart' as _i8; +import 'package:auto_route/auto_route.dart' as _i8; +import 'package:flutter/material.dart' as _i9; import '../layouts/main/index.dart' as _i1; -import '../screens/events/index.dart' as _i5; -import '../screens/home/index.dart' as _i3; -import '../screens/info/index.dart' as _i6; -import '../screens/map/index.dart' as _i4; -import '../screens/student_id/index.dart' as _i2; +import '../screens/events/index.dart' as _i4; +import '../screens/home/index.dart' as _i6; +import '../screens/info/index.dart' as _i5; +import '../screens/map/index.dart' as _i3; +import '../screens/student_id/index.dart' as _i7; +import '../utils/hero_empty_router_page.dart' as _i2; -class AppRouter extends _i7.RootStackRouter { - AppRouter([_i8.GlobalKey<_i8.NavigatorState>? navigatorKey]) +class AppRouter extends _i8.RootStackRouter { + AppRouter([_i9.GlobalKey<_i9.NavigatorState>? navigatorKey]) : super(navigatorKey); @override - final Map pagesMap = { + final Map pagesMap = { MainLayout.name: (routeData) { - return _i7.MaterialPageX( + return _i8.MaterialPageX( routeData: routeData, child: const _i1.MainLayout()); }, - StudentIdRoute.name: (routeData) { - return _i7.CustomPage( + HomePageRouter.name: (routeData) { + return _i8.MaterialPageX( + routeData: routeData, child: const _i2.HeroEmptyRouterPage()); + }, + MapRoute.name: (routeData) { + return _i8.MaterialPageX( + routeData: routeData, child: const _i3.MapScreen()); + }, + EventsRoute.name: (routeData) { + return _i8.MaterialPageX( + routeData: routeData, child: const _i4.EventsScreen()); + }, + InfoRoute.name: (routeData) { + return _i8.MaterialPageX( + routeData: routeData, child: const _i5.InfoScreen()); + }, + HomeRoute.name: (routeData) { + return _i8.CustomPage( routeData: routeData, - child: const _i2.StudentIdScreen(), - transitionsBuilder: _i7.TransitionsBuilders.slideTop, - durationInMilliseconds: 200, + child: const _i6.HomeScreen(), + transitionsBuilder: _i8.TransitionsBuilders.noTransition, opaque: true, barrierDismissible: false); }, - HomeRoute.name: (routeData) { - return _i7.MaterialPageX( - routeData: routeData, child: const _i3.HomeScreen()); - }, - MapRoute.name: (routeData) { - return _i7.MaterialPageX( - routeData: routeData, child: const _i4.MapScreen()); - }, - EventsRoute.name: (routeData) { - return _i7.MaterialPageX( - routeData: routeData, child: const _i5.EventsScreen()); - }, - InfoRoute.name: (routeData) { - return _i7.MaterialPageX( - routeData: routeData, child: const _i6.InfoScreen()); + StudentIdRoute.name: (routeData) { + return _i8.CustomPage( + routeData: routeData, + child: const _i7.StudentIdScreen(), + transitionsBuilder: _i8.TransitionsBuilders.noTransition, + opaque: true, + barrierDismissible: false); } }; @override - List<_i7.RouteConfig> get routes => [ - _i7.RouteConfig(MainLayout.name, path: '/', children: [ - _i7.RouteConfig(HomeRoute.name, - path: 'home', parent: MainLayout.name), - _i7.RouteConfig(MapRoute.name, path: 'map', parent: MainLayout.name), - _i7.RouteConfig(EventsRoute.name, + List<_i8.RouteConfig> get routes => [ + _i8.RouteConfig(MainLayout.name, path: '/', children: [ + _i8.RouteConfig(HomePageRouter.name, + path: 'home', + parent: MainLayout.name, + children: [ + _i8.RouteConfig(HomeRoute.name, + path: '', parent: HomePageRouter.name), + _i8.RouteConfig(StudentIdRoute.name, + path: 'student-id', parent: HomePageRouter.name) + ]), + _i8.RouteConfig(MapRoute.name, path: 'map', parent: MainLayout.name), + _i8.RouteConfig(EventsRoute.name, path: 'events', parent: MainLayout.name), - _i7.RouteConfig(InfoRoute.name, path: 'info', parent: MainLayout.name) - ]), - _i7.RouteConfig(StudentIdRoute.name, path: '/student-id') + _i8.RouteConfig(InfoRoute.name, path: 'info', parent: MainLayout.name) + ]) ]; } /// generated route for /// [_i1.MainLayout] -class MainLayout extends _i7.PageRouteInfo { - const MainLayout({List<_i7.PageRouteInfo>? children}) +class MainLayout extends _i8.PageRouteInfo { + const MainLayout({List<_i8.PageRouteInfo>? children}) : super(MainLayout.name, path: '/', initialChildren: children); static const String name = 'MainLayout'; } /// generated route for -/// [_i2.StudentIdScreen] -class StudentIdRoute extends _i7.PageRouteInfo { - const StudentIdRoute() : super(StudentIdRoute.name, path: '/student-id'); +/// [_i2.HeroEmptyRouterPage] +class HomePageRouter extends _i8.PageRouteInfo { + const HomePageRouter({List<_i8.PageRouteInfo>? children}) + : super(HomePageRouter.name, path: 'home', initialChildren: children); - static const String name = 'StudentIdRoute'; + static const String name = 'HomePageRouter'; } /// generated route for -/// [_i3.HomeScreen] -class HomeRoute extends _i7.PageRouteInfo { - const HomeRoute() : super(HomeRoute.name, path: 'home'); - - static const String name = 'HomeRoute'; -} - -/// generated route for -/// [_i4.MapScreen] -class MapRoute extends _i7.PageRouteInfo { +/// [_i3.MapScreen] +class MapRoute extends _i8.PageRouteInfo { const MapRoute() : super(MapRoute.name, path: 'map'); static const String name = 'MapRoute'; } /// generated route for -/// [_i5.EventsScreen] -class EventsRoute extends _i7.PageRouteInfo { +/// [_i4.EventsScreen] +class EventsRoute extends _i8.PageRouteInfo { const EventsRoute() : super(EventsRoute.name, path: 'events'); static const String name = 'EventsRoute'; } /// generated route for -/// [_i6.InfoScreen] -class InfoRoute extends _i7.PageRouteInfo { +/// [_i5.InfoScreen] +class InfoRoute extends _i8.PageRouteInfo { const InfoRoute() : super(InfoRoute.name, path: 'info'); static const String name = 'InfoRoute'; } + +/// generated route for +/// [_i6.HomeScreen] +class HomeRoute extends _i8.PageRouteInfo { + const HomeRoute() : super(HomeRoute.name, path: ''); + + static const String name = 'HomeRoute'; +} + +/// generated route for +/// [_i7.StudentIdScreen] +class StudentIdRoute extends _i8.PageRouteInfo { + const StudentIdRoute() : super(StudentIdRoute.name, path: 'student-id'); + + static const String name = 'StudentIdRoute'; +} diff --git a/lib/src/screens/home/index.dart b/lib/src/screens/home/index.dart index 6c2d09c..27483ac 100644 --- a/lib/src/screens/home/index.dart +++ b/lib/src/screens/home/index.dart @@ -9,9 +9,16 @@ import 'package:furman_now/src/widgets/home/restaurants/restaurants_list.dart'; import 'package:furman_now/src/widgets/home/transportation/transportation_card.dart'; import 'package:furman_now/src/widgets/scroll_view_height.dart'; -class HomeScreen extends StatelessWidget { +class HomeScreen extends StatefulWidget { const HomeScreen({Key? key}) : super(key: key); + @override + State createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State { + CrossFadeState _showScrollMessage = CrossFadeState.showFirst; + @override Widget build(BuildContext context) { return Scaffold( @@ -25,7 +32,7 @@ class HomeScreen extends StatelessWidget { children: [ Container( width: double.infinity, - height: double.infinity, + height: 300, decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, @@ -33,7 +40,7 @@ class HomeScreen extends StatelessWidget { colors: [ Color(0xffb7acc9), Color(0xffb7acc9), - ], // Gradient from https://learnui.design/tools/gradient-generator.html + ], tileMode: TileMode.mirror, ), ), @@ -47,9 +54,39 @@ class HomeScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("${greeting()},\nMichael", style: furmanTextStyle(const TextStyle(color: Color(0xff26183d), fontSize: 36, fontWeight: FontWeight.w800))), + Hero( + tag: "title", + child: Material( + type: MaterialType.transparency, + child: Text( + "${greeting()},\nMichael", + style: furmanTextStyle(const TextStyle( + color: Color(0xff26183d), + fontSize: 36, + fontWeight: FontWeight.w800, + )), + ), + ), + ), const SizedBox(height: 5), - Text("It's 76º and partly cloudy", style: furmanTextStyle(const TextStyle(color: Color(0xff26183d), fontSize: 16, fontWeight: FontWeight.w500))), + AnimatedCrossFade( + crossFadeState: _showScrollMessage, + duration: const Duration(milliseconds: 100), + firstChild: Text("It's 76º and partly cloudy", + style: furmanTextStyle(const TextStyle( + color: Color(0xff26183d), + fontSize: 16, + fontWeight: FontWeight.w500) + ), + ), + secondChild: Text("Pull down to view your Meal ID", + style: furmanTextStyle(const TextStyle( + color: Color(0xff26183d), + fontSize: 16, + fontWeight: FontWeight.w500) + ), + ), + ), ], ), ), @@ -63,39 +100,63 @@ class HomeScreen extends StatelessWidget { var offsetAmount = offset.abs(); if (offsetAmount > 50) { context.router.navigate(const StudentIdRoute()); + } else if (offsetAmount > 20) { + setState(() { + _showScrollMessage = CrossFadeState.showSecond; + }); + } else { + setState(() { + _showScrollMessage = CrossFadeState.showFirst; + }); + } + } else { + if (_showScrollMessage != CrossFadeState.showFirst) { + setState(() { + _showScrollMessage = CrossFadeState.showFirst; + }); } } } return true; }, child: ScrollViewWithHeight( - child: Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.vertical(top: Radius.circular(30)), - ), - padding: const EdgeInsets.symmetric(vertical: 20), - margin: const EdgeInsets.only(top: 200), - width: double.infinity, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const HeaderWidget( - title: "Today's Events", - link: HeaderLink(text: "View more", href: EventsRoute()), + child: Hero( + tag: "card", + child: Material( + type: MaterialType.transparency, + child: Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: + BorderRadius.vertical(top: Radius.circular(30)), ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: EventsList(), + padding: const EdgeInsets.symmetric(vertical: 20), + margin: const EdgeInsets.only(top: 200), + width: double.infinity, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const HeaderWidget( + title: "Today's Events", + link: HeaderLink( + text: "View more", + href: EventsRoute() + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: EventsList(), + ), + const HeaderWidget(title: "Food & Dining"), + const RestaurantsList(), + const HeaderWidget(title: "Transportation"), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 20), + child: TransportationCard(), + ), + ], ), - const HeaderWidget(title: "Food & Dining"), - const RestaurantsList(), - const HeaderWidget(title: "Transportation"), - const Padding( - padding: EdgeInsets.symmetric(horizontal: 20), - child: TransportationCard(), - ), - ], + ), ), ), ), diff --git a/lib/src/screens/student_id/index.dart b/lib/src/screens/student_id/index.dart index b301e26..7cd477e 100644 --- a/lib/src/screens/student_id/index.dart +++ b/lib/src/screens/student_id/index.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:barcode_widget/barcode_widget.dart'; +import 'package:flutter_remix/flutter_remix.dart'; import 'package:furman_now/src/routes/index.gr.dart'; import 'package:furman_now/src/services/get_app/barcode/barcode_service.dart'; import 'package:furman_now/src/utils/theme.dart'; @@ -49,40 +50,119 @@ class _StudentIdScreenState extends State { if (details.delta.dy > sensitivity) { // Down Swipe } else if (details.delta.dy < -sensitivity) { - context.router.navigate(const MainLayout()); + context.router.navigate(const HomeRoute()); } }, - child: Container( - color: const Color(0xffb7acc9), - child: SafeArea( - child: ListView( - padding: const EdgeInsets.all(40), - children: [ - Text( - "Furman ID", - style: furmanTextStyle(const TextStyle(color: Color(0xff26183d), fontSize: 36, fontWeight: FontWeight.w800)), + child: Stack( + children: [ + Container( + color: const Color(0xffb7acc9), + child: SafeArea( + child: ListView( + padding: const EdgeInsets.all(40), + children: [ + Hero( + tag: "title", + child: Material( + type: MaterialType.transparency, + child: Text( + "Furman ID", + style: furmanTextStyle(const TextStyle( + color: Color(0xff26183d), + fontSize: 36, + fontWeight: FontWeight.w800 + )), + ), + ), + ), + const SizedBox(height: 30), + Center( + child: Container( + height: 200, + width: 200, + decoration: BoxDecoration( + color: Colors.grey[200], + borderRadius: BorderRadius.circular(40), + ), + child: Icon( + FlutterRemix.user_3_line, + size: 120, + color: Colors.grey[400], + ), + ), + ), + const SizedBox(height: 20), + Center(child: Text( + "Michael Thomas", + style: furmanTextStyle(const TextStyle( + color: Color(0xff26183d), + fontSize: 28, + fontWeight: FontWeight.w700 + )), + )), + const SizedBox(height: 5), + Center(child: Text( + "5001962", + style: furmanTextStyle(const TextStyle( + color: Color(0xff26183d), + fontSize: 20, + fontWeight: FontWeight.w500 + )), + )), + const SizedBox(height: 20), + Container( + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.all(Radius.circular(10)), + ), + // hack since the barcode has a weird intrinsic size for some reason + child: LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return BarcodeWidget( + barcode: Barcode.pdf417(moduleHeight: 4), + data: barcodeNumber, + margin: const EdgeInsets.all(10), + height: constraints.maxWidth / 3, + ); + }, + ), + ), + ], ), - const SizedBox(height: 200), - Container( - decoration: const BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(10)), - ), - // hack since the barcode has a weird intrinsic size for some reason - child: LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - return BarcodeWidget( - barcode: Barcode.pdf417(moduleHeight: 4), - data: barcodeNumber, - margin: const EdgeInsets.all(10), - height: constraints.maxWidth / 3, - ); - }, - ), - ), - ], + ), ), - ), + Align( + alignment: Alignment.bottomCenter, + child: Hero( + tag: "card", + child: Material( + type: MaterialType.transparency, + child: Container( + height: 75, + width: double.infinity, + decoration: const BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.vertical( + top: Radius.circular(30), + ), + ), + child: Align( + alignment: Alignment.topCenter, + child: Container( + margin: const EdgeInsets.only(top: 10), + width: 40, + height: 5, + decoration: BoxDecoration( + color: Colors.grey[400], + borderRadius: BorderRadius.circular(20), + ) + ), + ), + ), + ), + ), + ), + ], ), ), ); diff --git a/lib/src/store/index.dart b/lib/src/store/index.dart new file mode 100644 index 0000000..69080bf --- /dev/null +++ b/lib/src/store/index.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:furman_now/src/services/events/event.dart'; +import 'package:furman_now/src/services/events/events_service.dart'; +import 'package:furman_now/src/services/restaurants/restaurant_service.dart'; + +class AppState extends ChangeNotifier { + late Future> events; + late Future> restaurants; + + AppState() { + refresh(); + } + + void refresh() { + events = EventsService.fetchEvents(); + restaurants = RestaurantService.fetchRestaurants(); + notifyListeners(); + } + + @override + int get hashCode => + events.hashCode ^ + restaurants.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is AppState && + runtimeType == other.runtimeType && + events == other.events && + restaurants == other.restaurants; + +} \ No newline at end of file diff --git a/lib/src/utils/hero_empty_router_page.dart b/lib/src/utils/hero_empty_router_page.dart new file mode 100644 index 0000000..02f3d9b --- /dev/null +++ b/lib/src/utils/hero_empty_router_page.dart @@ -0,0 +1,14 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; + +class HeroEmptyRouterPage extends StatelessWidget { + const HeroEmptyRouterPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return HeroControllerScope( + controller: HeroController(), + child: const AutoRouter(), + ); + } +} diff --git a/lib/src/widgets/events/events_list.dart b/lib/src/widgets/events/events_list.dart index 6c40697..6f2fd3a 100644 --- a/lib/src/widgets/events/events_list.dart +++ b/lib/src/widgets/events/events_list.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; import 'package:furman_now/src/services/events/event.dart'; -import 'package:furman_now/src/services/events/events_service.dart'; +import 'package:furman_now/src/store/index.dart'; import 'package:furman_now/src/utils/theme.dart'; +import 'package:provider/provider.dart'; import 'event_card.dart'; @@ -34,62 +35,61 @@ class EventsList extends StatefulWidget { } class _EventsListState extends State { - late Future> futureEventList; - - @override - void initState() { - super.initState(); - futureEventList = EventsService.fetchEvents(); - } @override Widget build(BuildContext context) { - return FutureBuilder>( - future: futureEventList, - builder: (context, snapshot) { - if (snapshot.hasData) { - var events = snapshot.data!.where((event) { - return event.time.isAfter(widget.dateRange.start) && event.time.isBefore(widget.dateRange.end); - }); - if (events.isNotEmpty) { - return Column( - children: events.map((event) { - return Padding( - padding: const EdgeInsets.only(bottom: 15), - child: EventCard(event), - ); - }).toList()); - } else { - return Padding( - padding: const EdgeInsets.only(bottom: 15), - child: SizedBox( - width: double.infinity, - height: 50, - child: Center( - child: Text( - "No events today :(", - style: furmanTextStyle(TextStyle( - color: Colors.grey[600], - fontSize: 16, - fontWeight: FontWeight.w600, - )), + return Consumer( + builder: (context, state, child) { + return FutureBuilder>( + future: state.events, + builder: (context, snapshot) { + if (snapshot.hasData) { + var events = snapshot.data!.where((event) { + return event.time.isAfter(widget.dateRange.start) && + event.time.isBefore(widget.dateRange.end); + }); + if (events.isNotEmpty) { + return Column( + children: events.map((event) { + return Padding( + padding: const EdgeInsets.only(bottom: 15), + child: EventCard(event), + ); + }).toList()); + } else { + return Padding( + padding: const EdgeInsets.only(bottom: 15), + child: SizedBox( + width: double.infinity, + height: 50, + child: Center( + child: Text( + "No events today :(", + style: furmanTextStyle(TextStyle( + color: Colors.grey[600], + fontSize: 16, + fontWeight: FontWeight.w600, + )), + ), + ), ), - ), + ); + } + } else if (snapshot.hasError) { + return Text( + '${snapshot.error}', style: const TextStyle(color: Colors.red),); + } + + // By default, show a loading spinner. + return const Center( + child: Padding( + padding: EdgeInsets.symmetric(vertical: 25), + child: CircularProgressIndicator() ), ); - } - } else if (snapshot.hasError) { - return Text('${snapshot.error}', style: const TextStyle(color: Colors.red),); - } - - // By default, show a loading spinner. - return const Center( - child: Padding( - padding: EdgeInsets.symmetric(vertical: 25), - child: CircularProgressIndicator() - ), + }, ); - }, + } ); } } \ No newline at end of file diff --git a/lib/src/widgets/home/restaurants/restaurants_list.dart b/lib/src/widgets/home/restaurants/restaurants_list.dart index fd71173..8191dca 100644 --- a/lib/src/widgets/home/restaurants/restaurants_list.dart +++ b/lib/src/widgets/home/restaurants/restaurants_list.dart @@ -1,5 +1,7 @@ import 'package:flutter/material.dart'; import 'package:furman_now/src/services/restaurants/restaurant_service.dart'; +import 'package:furman_now/src/store/index.dart'; +import 'package:provider/provider.dart'; import 'restaurant_card.dart'; @@ -11,51 +13,47 @@ class RestaurantsList extends StatefulWidget { } class _RestaurantsListState extends State { - late Future> futureEventList; - - @override - void initState() { - super.initState(); - futureEventList = RestaurantService.fetchRestaurants(); - } - @override Widget build(BuildContext context) { - return FutureBuilder>( - future: futureEventList, - builder: (context, snapshot) { - if (snapshot.hasData) { - var restaurants = snapshot.data!..sort((r1, r2) => (r1.isOpen ? 0 : 1) - (r2.isOpen ? 0 : 1)); - return SizedBox( - height: 175, - child: ListView.builder( - padding: const EdgeInsets.only(left: 20), - itemCount: restaurants.length, - cacheExtent: 10000, - scrollDirection: Axis.horizontal, - prototypeItem: Padding( - padding: const EdgeInsets.only(right: 15), - child: RestaurantCard(restaurant: restaurants.first), - ), - itemBuilder: (context, index) => Padding( - padding: const EdgeInsets.only(right: 15), - child: RestaurantCard(restaurant: restaurants[index]), - ), - ), - ); - } else if (snapshot.hasError) { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Text('${snapshot.error}', style: const TextStyle(color: Colors.red)) - ); - } + return Consumer( + builder: (context, state, child) { + return FutureBuilder>( + future: state.restaurants, + builder: (context, snapshot) { + if (snapshot.hasData) { + var restaurants = snapshot.data!..sort((r1, r2) => (r1.isOpen ? 0 : 1) - (r2.isOpen ? 0 : 1)); + return SizedBox( + height: 175, + child: ListView.builder( + padding: const EdgeInsets.only(left: 20), + itemCount: restaurants.length, + cacheExtent: 10000, + scrollDirection: Axis.horizontal, + prototypeItem: Padding( + padding: const EdgeInsets.only(right: 15), + child: RestaurantCard(restaurant: restaurants.first), + ), + itemBuilder: (context, index) => Padding( + padding: const EdgeInsets.only(right: 15), + child: RestaurantCard(restaurant: restaurants[index]), + ), + ), + ); + } else if (snapshot.hasError) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Text('${snapshot.error}', style: const TextStyle(color: Colors.red)) + ); + } - // By default, show a loading spinner. - return const Center( - child: Padding( - padding: EdgeInsets.symmetric(vertical: 25), - child: CircularProgressIndicator() - ), + // By default, show a loading spinner. + return const Center( + child: Padding( + padding: EdgeInsets.symmetric(vertical: 25), + child: CircularProgressIndicator() + ), + ); + }, ); }, ); diff --git a/pubspec.lock b/pubspec.lock index 6293e2f..2194208 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -265,6 +265,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.1.4" + flutter_remix: + dependency: "direct main" + description: + name: flutter_remix + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.3" flutter_svg: dependency: "direct main" description: @@ -464,6 +471,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.2" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" node_preamble: dependency: transitive description: @@ -611,6 +625,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.3" pub_semver: dependency: transitive description: @@ -639,6 +660,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.0" + salomon_bottom_bar: + dependency: "direct main" + description: + name: salomon_bottom_bar + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.1" shelf: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index b833515..330dfd3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -47,6 +47,9 @@ dependencies: flutter_svg: ^1.1.4 auto_route: ^5.0.1 flutter_map_location_marker: ^4.1.4 + salomon_bottom_bar: ^3.3.1 + flutter_remix: ^0.0.3 + provider: ^6.0.3 dev_dependencies: flutter_test: