fix: various improvements to events list

This commit is contained in:
Michael Thomas 2023-02-09 20:03:16 -05:00
parent d0d881fbbe
commit 2052e618ac
4 changed files with 111 additions and 164 deletions

View File

@ -19,10 +19,21 @@ class EventsService {
if (response.statusCode == 200) { if (response.statusCode == 200) {
// If the server did return a 200 OK response, // If the server did return a 200 OK response,
// then parse the JSON. // then parse the JSON.
final eventsJson = jsonDecode(response.body); try {
return (eventsJson["results"] as List<dynamic>).map((event) => final eventsJson = jsonDecode(response.body);
AthleticsEvent.fromJson(event) if (eventsJson["results"] != null) {
); return (eventsJson["results"] as List<dynamic>).map((event) =>
AthleticsEvent.fromJson(event)
);
} else {
return [];
}
} catch (e) {
throw
"Failed to parse athletics event data."
"\n"
"Exception: $e";
}
} else { } else {
// If the server did not return a 200 OK response, // If the server did not return a 200 OK response,
// then throw an exception. // then throw an exception.
@ -37,14 +48,26 @@ class EventsService {
if (response.statusCode == 200) { if (response.statusCode == 200) {
// If the server did return a 200 OK response, // If the server did return a 200 OK response,
// then parse the JSON. // then parse the JSON.
final eventsJson = jsonDecode(response.body); try {
return (eventsJson["results"] as List<dynamic>).map((event) => final eventsJson = jsonDecode(response.body);
ClpEvent.fromJson(event) if (eventsJson["results"] != null) {
); return (eventsJson["results"] as List<dynamic>).map((event) =>
ClpEvent.fromJson(event)
);
} else {
return [];
}
} catch (e) {
throw
"Failed to parse CLP event data."
"\n"
"Exception: $e";
}
} else { } else {
// If the server did not return a 200 OK response, // If the server did not return a 200 OK response,
// then throw an exception. // then throw an exception.
throw Exception('Failed to load athletics events.'); throw Exception('Failed to load CLP events.');
} }
} }
} }

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:furman_now/src/services/events/event.dart'; import 'package:furman_now/src/services/events/event.dart';
import 'package:furman_now/src/utils/theme.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/events/event_modal.dart';
import 'package:furman_now/src/widgets/text_with_icon.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
class EventCard extends StatelessWidget { class EventCard extends StatelessWidget {
@ -33,12 +34,6 @@ class EventCard extends StatelessWidget {
context, context,
event, event,
); );
// showModalBottomSheet<void>(
// context: context,
// builder: (BuildContext context) {
// return EventModal(event: event);
// }
// );
}, },
child: Container( child: Container(
decoration: const BoxDecoration( decoration: const BoxDecoration(
@ -53,8 +48,11 @@ class EventCard extends StatelessWidget {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Text(eventHour, style: furmanTextStyle(const TextStyle(fontWeight: FontWeight.w700))), Text(eventHour, style: furmanTextStyle(TextStyle(
Text(eventAmPm, style: Theme.of(context).textTheme.subtitle2), 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( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(event.title, style: furmanTextStyle(const TextStyle(fontWeight: FontWeight.w600))), Text(event.title, style: Theme.of(context).textTheme.titleSmall),
const SizedBox(height: 6), const SizedBox(height: 6),
RichText(text: TextSpan( TextWithIcon(
style: Theme.of(context).textTheme.subtitle2, icon: Icons.place_outlined,
children: [ text: event.location,
WidgetSpan( size: TextWithIconSize.small,
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),
],
)),
const SizedBox(height: 2), const SizedBox(height: 2),
RichText(text: TextSpan( TextWithIcon(
style: Theme.of(context).textTheme.subtitle2, icon: Icons.sell_outlined,
children: [ text: event.category,
WidgetSpan( size: TextWithIconSize.small,
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),
],
)),
], ],
), ),
), ),

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:furman_now/src/services/events/event.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/events/events_service.dart';
import 'package:furman_now/src/widgets/text_with_icon.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
void showEventsModal(BuildContext context, Event event) { void showEventsModal(BuildContext context, Event event) {
@ -31,16 +32,19 @@ class _EventModalState extends State<_EventModal> {
BoxConstraints? _parentConstraints; BoxConstraints? _parentConstraints;
final _key = GlobalKey(); final _key = GlobalKey();
double _maxChildHeight = 0.75; static const _maxDialogHeight = 0.8;
var _maxChildHeight = _maxDialogHeight;
void updateMaxHeight() { void updateMaxHeight() {
if (_parentConstraints != null) { if (_parentConstraints != null) {
var listHeight = _key.currentContext?.size?.height; var listHeight = _key.currentContext?.size?.height;
var parentHeight = _parentConstraints?.maxHeight; var parentHeight = _parentConstraints?.maxHeight;
if (listHeight != null && parentHeight != null) { if (listHeight != null && parentHeight != null) {
var maxHeight = (listHeight + 50) / parentHeight; var maxHeight = (listHeight + 70) / parentHeight;
setState(() { setState(() {
_maxChildHeight = (maxHeight < 0.75) ? maxHeight : 0.75; _maxChildHeight = (maxHeight < _maxDialogHeight)
? maxHeight : _maxDialogHeight;
}); });
} }
} }
@ -78,11 +82,13 @@ class _EventModalState extends State<_EventModal> {
child: CloseButton(), child: CloseButton(),
), ),
Flexible( Flexible(
child: NotificationListener<OverscrollIndicatorNotification>( child: NotificationListener
onNotification: (OverscrollIndicatorNotification overscroll) { <OverscrollIndicatorNotification>(
overscroll.disallowIndicator(); onNotification:
return true; (OverscrollIndicatorNotification overscroll) {
}, overscroll.disallowIndicator();
return true;
},
child: _EventModalContent( child: _EventModalContent(
key: _key, key: _key,
controller: controller, controller: controller,
@ -123,120 +129,55 @@ class _EventModalContent extends StatelessWidget {
// Title // Title
Text( Text(
event.title, event.title,
style: Theme.of(context).textTheme.headline1, style: Theme.of(context).textTheme.headlineLarge,
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
// Location // Location
RichText(text: TextSpan( TextWithIcon(
style: Theme.of(context).textTheme.subtitle1, icon: Icons.place_outlined,
children: [ text: event.location,
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),
],
)),
const SizedBox(height: 5), const SizedBox(height: 5),
if (event is ClpEvent) ...[ // Additional info for CLP events
// Organization if (event is ClpEvent) ...(() {
RichText(text: TextSpan( final clpEvent = event as ClpEvent;
style: Theme.of(context).textTheme.subtitle1, return [
children: [ // Organization
WidgetSpan( TextWithIcon(
alignment: PlaceholderAlignment.middle, icon: Icons.group_outlined,
child: Padding( text: clpEvent.organization
padding: const EdgeInsets.only(right: 5.0), ),
child: Icon( const SizedBox(height: 5),
Icons.group_outlined, // Time
size: 24, TextWithIcon(
color: Colors.grey[500] icon: Icons.access_time_outlined,
), text:
), "${DateFormat("EEEE, MMMM d").format(clpEvent.startTime)}"
), "\n"
TextSpan(text: (event as ClpEvent).organization), "${DateFormat.jm().format(clpEvent.startTime)} - ${DateFormat.jm().format(clpEvent.endTime)}",
], ),
)), const SizedBox(height: 5),
const SizedBox(height: 5), // Description
// Time TextWithIcon(
RichText(text: TextSpan( icon: Icons.notes,
style: Theme.of(context).textTheme.subtitle1, text: clpEvent.description
children: [ ),
WidgetSpan( ];
alignment: PlaceholderAlignment.middle, })(),
child: Padding( // Additional info for Athletics Events
padding: const EdgeInsets.only( if (event is AthleticsEvent) ...(() {
right: 5.0), final athleticsEvent = event as AthleticsEvent;
child: Icon( return [
Icons.access_time_outlined, // Time
size: 24, TextWithIcon(
color: Colors.grey[500]) icon: Icons.access_time_outlined,
), text:
), "${DateFormat("EEEE, MMMM d").format(athleticsEvent.time)}"
WidgetSpan( "\n"
alignment: PlaceholderAlignment.top, "${DateFormat.jm().format(athleticsEvent.time)}",
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,
),
),
],
),
]
], ],
); );
} }

View File

@ -20,9 +20,10 @@ class EventsList extends StatefulWidget {
}) { }) {
if (dateRange == null) { if (dateRange == null) {
final now = DateTime.now(); 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); 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._( return EventsList._(
dateRange: dateRange, dateRange: dateRange,