diff --git a/lib/src/services/events/events_service.dart b/lib/src/services/events/events_service.dart index fc3a2f7..9d8f9e5 100644 --- a/lib/src/services/events/events_service.dart +++ b/lib/src/services/events/events_service.dart @@ -19,10 +19,21 @@ class EventsService { if (response.statusCode == 200) { // If the server did return a 200 OK response, // then parse the JSON. - final eventsJson = jsonDecode(response.body); - return (eventsJson["results"] as List).map((event) => - AthleticsEvent.fromJson(event) - ); + try { + final eventsJson = jsonDecode(response.body); + if (eventsJson["results"] != null) { + return (eventsJson["results"] as List).map((event) => + AthleticsEvent.fromJson(event) + ); + } else { + return []; + } + } catch (e) { + throw + "Failed to parse athletics event data." + "\n" + "Exception: $e"; + } } else { // If the server did not return a 200 OK response, // then throw an exception. @@ -37,14 +48,26 @@ class EventsService { if (response.statusCode == 200) { // If the server did return a 200 OK response, // then parse the JSON. - final eventsJson = jsonDecode(response.body); - return (eventsJson["results"] as List).map((event) => - ClpEvent.fromJson(event) - ); + try { + final eventsJson = jsonDecode(response.body); + if (eventsJson["results"] != null) { + return (eventsJson["results"] as List).map((event) => + ClpEvent.fromJson(event) + ); + } else { + return []; + } + } catch (e) { + throw + "Failed to parse CLP event data." + "\n" + "Exception: $e"; + } + } else { // If the server did not return a 200 OK response, // then throw an exception. - throw Exception('Failed to load athletics events.'); + throw Exception('Failed to load CLP events.'); } } } diff --git a/lib/src/widgets/events/event_card.dart b/lib/src/widgets/events/event_card.dart index 2893b88..9f6eec4 100644 --- a/lib/src/widgets/events/event_card.dart +++ b/lib/src/widgets/events/event_card.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:furman_now/src/services/events/event.dart'; import 'package:furman_now/src/utils/theme.dart'; import 'package:furman_now/src/widgets/events/event_modal.dart'; +import 'package:furman_now/src/widgets/text_with_icon.dart'; import 'package:intl/intl.dart'; class EventCard extends StatelessWidget { @@ -33,12 +34,6 @@ class EventCard extends StatelessWidget { context, event, ); - // showModalBottomSheet( - // context: context, - // builder: (BuildContext context) { - // return EventModal(event: event); - // } - // ); }, child: Container( decoration: const BoxDecoration( @@ -53,8 +48,11 @@ class EventCard extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(eventHour, style: furmanTextStyle(const TextStyle(fontWeight: FontWeight.w700))), - Text(eventAmPm, style: Theme.of(context).textTheme.subtitle2), + Text(eventHour, style: furmanTextStyle(TextStyle( + color: Colors.grey[800], + fontWeight: FontWeight.w700 + ))), + Text(eventAmPm, style: Theme.of(context).textTheme.labelMedium), ], ), ), @@ -69,35 +67,19 @@ class EventCard extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(event.title, style: furmanTextStyle(const TextStyle(fontWeight: FontWeight.w600))), + Text(event.title, style: Theme.of(context).textTheme.titleSmall), const SizedBox(height: 6), - RichText(text: TextSpan( - style: Theme.of(context).textTheme.subtitle2, - children: [ - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Padding( - padding: const EdgeInsets.only(right: 5.0), - child: Icon(Icons.place_outlined, size: 20, color: Colors.grey[500]) - ), - ), - TextSpan(text: event.location), - ], - )), + TextWithIcon( + icon: Icons.place_outlined, + text: event.location, + size: TextWithIconSize.small, + ), const SizedBox(height: 2), - RichText(text: TextSpan( - style: Theme.of(context).textTheme.subtitle2, - children: [ - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Padding( - padding: const EdgeInsets.only(left: 1.0, right: 6.0), - child: Icon(Icons.sell_outlined, size: 18, color: Colors.grey[500]) - ), - ), - TextSpan(text: event.category), - ], - )), + TextWithIcon( + icon: Icons.sell_outlined, + text: event.category, + size: TextWithIconSize.small, + ), ], ), ), diff --git a/lib/src/widgets/events/event_modal.dart b/lib/src/widgets/events/event_modal.dart index 1ed220e..0f40d88 100644 --- a/lib/src/widgets/events/event_modal.dart +++ b/lib/src/widgets/events/event_modal.dart @@ -1,6 +1,7 @@ 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/widgets/text_with_icon.dart'; import 'package:intl/intl.dart'; void showEventsModal(BuildContext context, Event event) { @@ -30,17 +31,20 @@ class _EventModalState extends State<_EventModal> { var childSize = Size.zero; BoxConstraints? _parentConstraints; final _key = GlobalKey(); + + static const _maxDialogHeight = 0.8; - double _maxChildHeight = 0.75; + var _maxChildHeight = _maxDialogHeight; void updateMaxHeight() { if (_parentConstraints != null) { var listHeight = _key.currentContext?.size?.height; var parentHeight = _parentConstraints?.maxHeight; if (listHeight != null && parentHeight != null) { - var maxHeight = (listHeight + 50) / parentHeight; + var maxHeight = (listHeight + 70) / parentHeight; setState(() { - _maxChildHeight = (maxHeight < 0.75) ? maxHeight : 0.75; + _maxChildHeight = (maxHeight < _maxDialogHeight) + ? maxHeight : _maxDialogHeight; }); } } @@ -78,11 +82,13 @@ class _EventModalState extends State<_EventModal> { child: CloseButton(), ), Flexible( - child: NotificationListener( - onNotification: (OverscrollIndicatorNotification overscroll) { - overscroll.disallowIndicator(); - return true; - }, + child: NotificationListener + ( + onNotification: + (OverscrollIndicatorNotification overscroll) { + overscroll.disallowIndicator(); + return true; + }, child: _EventModalContent( key: _key, controller: controller, @@ -123,120 +129,55 @@ class _EventModalContent extends StatelessWidget { // Title Text( event.title, - style: Theme.of(context).textTheme.headline1, + style: Theme.of(context).textTheme.headlineLarge, ), const SizedBox(height: 10), // Location - RichText(text: TextSpan( - style: Theme.of(context).textTheme.subtitle1, - children: [ - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Padding( - padding: const EdgeInsets.only(right: 5.0), - child: Icon( - Icons.place_outlined, size: 24, - color: Colors.grey[500]) - ), - ), - TextSpan(text: event.location), - ], - )), + TextWithIcon( + icon: Icons.place_outlined, + text: event.location, + ), const SizedBox(height: 5), - if (event is ClpEvent) ...[ - // Organization - RichText(text: TextSpan( - style: Theme.of(context).textTheme.subtitle1, - children: [ - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Padding( - padding: const EdgeInsets.only(right: 5.0), - child: Icon( - Icons.group_outlined, - size: 24, - color: Colors.grey[500] - ), - ), - ), - TextSpan(text: (event as ClpEvent).organization), - ], - )), - const SizedBox(height: 5), - // Time - RichText(text: TextSpan( - style: Theme.of(context).textTheme.subtitle1, - children: [ - WidgetSpan( - alignment: PlaceholderAlignment.middle, - child: Padding( - padding: const EdgeInsets.only( - right: 5.0), - child: Icon( - Icons.access_time_outlined, - size: 24, - color: Colors.grey[500]) - ), - ), - WidgetSpan( - alignment: PlaceholderAlignment.top, - child: Column( - crossAxisAlignment: CrossAxisAlignment - .start, - children: [ - Text( - DateFormat("EEEE, MMMM d") - .format( - (event as ClpEvent) - .startTime), - style: Theme - .of(context) - .textTheme - .subtitle1, - ), - Text( - "${DateFormat.jm().format( - (event as ClpEvent) - .startTime)} - ${DateFormat - .jm().format( - (event as ClpEvent) - .endTime)}", - style: Theme - .of(context) - .textTheme - .subtitle1, - ), - ], - ) - ), - ], - )), - const SizedBox(height: 5), - // Description - Row( - crossAxisAlignment: CrossAxisAlignment - .start, - children: [ - Padding( - padding: const EdgeInsets.only( - right: 5.0), - child: Icon(Icons.notes, size: 24, - color: Colors - .grey[500]) - ), - Flexible( - child: Text( - (event as ClpEvent) - .description, - style: Theme - .of(context) - .textTheme - .subtitle1, - ), - ), - ], - ), - ] + // Additional info for CLP events + if (event is ClpEvent) ...(() { + final clpEvent = event as ClpEvent; + return [ + // Organization + TextWithIcon( + icon: Icons.group_outlined, + text: clpEvent.organization + ), + const SizedBox(height: 5), + // Time + TextWithIcon( + icon: Icons.access_time_outlined, + text: + "${DateFormat("EEEE, MMMM d").format(clpEvent.startTime)}" + "\n" + "${DateFormat.jm().format(clpEvent.startTime)} - ${DateFormat.jm().format(clpEvent.endTime)}", + ), + const SizedBox(height: 5), + // Description + TextWithIcon( + icon: Icons.notes, + text: clpEvent.description + ), + ]; + })(), + // Additional info for Athletics Events + if (event is AthleticsEvent) ...(() { + final athleticsEvent = event as AthleticsEvent; + return [ + // Time + TextWithIcon( + icon: Icons.access_time_outlined, + text: + "${DateFormat("EEEE, MMMM d").format(athleticsEvent.time)}" + "\n" + "${DateFormat.jm().format(athleticsEvent.time)}", + ), + ]; + })(), ], ); } diff --git a/lib/src/widgets/events/events_list.dart b/lib/src/widgets/events/events_list.dart index 6f2fd3a..f0e0f71 100644 --- a/lib/src/widgets/events/events_list.dart +++ b/lib/src/widgets/events/events_list.dart @@ -20,9 +20,10 @@ class EventsList extends StatefulWidget { }) { if (dateRange == null) { final now = DateTime.now(); - final today = DateTime(now.year, now.month, now.day); + // final today = DateTime(now.year, now.month, now.day); final tonight = DateTime(now.year, now.month, now.day, 23, 59, 59); - dateRange = DateTimeRange(start: today, end: tonight); + // dateRange = DateTimeRange(start: today, end: tonight); + dateRange = DateTimeRange(start: now, end: tonight); } return EventsList._( dateRange: dateRange,