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.
try {
final eventsJson = jsonDecode(response.body); final eventsJson = jsonDecode(response.body);
if (eventsJson["results"] != null) {
return (eventsJson["results"] as List<dynamic>).map((event) => return (eventsJson["results"] as List<dynamic>).map((event) =>
AthleticsEvent.fromJson(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.
try {
final eventsJson = jsonDecode(response.body); final eventsJson = jsonDecode(response.body);
if (eventsJson["results"] != null) {
return (eventsJson["results"] as List<dynamic>).map((event) => return (eventsJson["results"] as List<dynamic>).map((event) =>
ClpEvent.fromJson(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,8 +82,10 @@ class _EventModalState extends State<_EventModal> {
child: CloseButton(), child: CloseButton(),
), ),
Flexible( Flexible(
child: NotificationListener<OverscrollIndicatorNotification>( child: NotificationListener
onNotification: (OverscrollIndicatorNotification overscroll) { <OverscrollIndicatorNotification>(
onNotification:
(OverscrollIndicatorNotification overscroll) {
overscroll.disallowIndicator(); overscroll.disallowIndicator();
return true; return true;
}, },
@ -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
if (event is ClpEvent) ...(() {
final clpEvent = event as ClpEvent;
return [
// Organization // Organization
RichText(text: TextSpan( TextWithIcon(
style: Theme.of(context).textTheme.subtitle1, icon: Icons.group_outlined,
children: [ text: clpEvent.organization
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), const SizedBox(height: 5),
// Time // Time
RichText(text: TextSpan( TextWithIcon(
style: Theme.of(context).textTheme.subtitle1, icon: Icons.access_time_outlined,
children: [ text:
WidgetSpan( "${DateFormat("EEEE, MMMM d").format(clpEvent.startTime)}"
alignment: PlaceholderAlignment.middle, "\n"
child: Padding( "${DateFormat.jm().format(clpEvent.startTime)} - ${DateFormat.jm().format(clpEvent.endTime)}",
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), const SizedBox(height: 5),
// Description // Description
Row( TextWithIcon(
crossAxisAlignment: CrossAxisAlignment icon: Icons.notes,
.start, text: clpEvent.description
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) // Additional info for Athletics Events
.description, if (event is AthleticsEvent) ...(() {
style: Theme final athleticsEvent = event as AthleticsEvent;
.of(context) return [
.textTheme // Time
.subtitle1, TextWithIcon(
icon: Icons.access_time_outlined,
text:
"${DateFormat("EEEE, MMMM d").format(athleticsEvent.time)}"
"\n"
"${DateFormat.jm().format(athleticsEvent.time)}",
), ),
), ];
], })(),
),
]
], ],
); );
} }

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,