Show event information in bottom modal

This commit is contained in:
Michael Thomas 2022-09-03 13:14:02 -04:00
parent 17350d798d
commit 7ca45d2f70
7 changed files with 368 additions and 99 deletions

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:furman_now/src/utils/date_range.dart';
import 'package:furman_now/src/utils/theme.dart';
import 'package:furman_now/src/widgets/header.dart';
import 'package:furman_now/src/widgets/home/events/events_list.dart';
import 'package:furman_now/src/widgets/events/events_list.dart';
import 'package:furman_now/src/widgets/scroll_view_height.dart';
import 'package:intl/intl.dart';

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:furman_now/src/utils/greeting.dart';
import 'package:furman_now/src/utils/theme.dart';
import 'package:furman_now/src/widgets/header.dart';
import 'package:furman_now/src/widgets/home/events/events_list.dart';
import 'package:furman_now/src/widgets/events/events_list.dart';
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';

View File

@ -8,6 +8,16 @@ ThemeData _baseTheme = ThemeData(
unselectedItemColor: Colors.grey[500],
),
textTheme: TextTheme(
headline1: TextStyle(
color: Colors.grey[800],
fontWeight: FontWeight.w900,
fontSize: 22,
),
subtitle1: TextStyle(
color: Colors.grey[500],
fontWeight: FontWeight.w500,
fontSize: 16,
),
subtitle2: TextStyle(
color: Colors.grey[500],
fontWeight: FontWeight.w500,

View File

@ -0,0 +1,111 @@
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:intl/intl.dart';
class EventCard extends StatelessWidget {
const EventCard
(
this.event,
{
Key? key
}
) : super(key: key);
final Event event;
String get eventHour {
var formatter = DateFormat('hh:mm');
return formatter.format(event.time);
}
String get eventAmPm {
var formatter = DateFormat('a');
return formatter.format(event.time);
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
showEventsModal(
context,
event,
);
// showModalBottomSheet<void>(
// context: context,
// builder: (BuildContext context) {
// return EventModal(event: event);
// }
// );
},
child: Container(
decoration: const BoxDecoration(
color: Color(0xfff9f9fb),
borderRadius: BorderRadius.all(Radius.circular(10))
),
child: IntrinsicHeight(
child: Row(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(eventHour, style: furmanTextStyle(const TextStyle(fontWeight: FontWeight.w700))),
Text(eventAmPm, style: Theme.of(context).textTheme.subtitle2),
],
),
),
VerticalDivider(
width: 2,
thickness: 2,
color: Colors.grey[200],
),
Flexible(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(event.title, style: furmanTextStyle(const TextStyle(fontWeight: FontWeight.w600))),
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),
],
)),
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),
],
)),
],
),
),
),
],
),
),
),
);
}
}

View File

@ -0,0 +1,245 @@
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:intl/intl.dart';
void showEventsModal(BuildContext context, Event event) {
showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) {
return _EventModal(event: event);
},
);
}
class _EventModal extends StatefulWidget {
final Event event;
const _EventModal({
required this.event,
Key? key,
}) : super(key: key);
@override
State<_EventModal> createState() => _EventModalState();
}
class _EventModalState extends State<_EventModal> {
var childSize = Size.zero;
BoxConstraints? _parentConstraints;
final _key = GlobalKey();
double _maxChildHeight = 0.75;
void updateMaxHeight() {
if (_parentConstraints != null) {
print(_key.currentContext?.size?.height);
var listHeight = _key.currentContext?.size?.height;
var parentHeight = _parentConstraints?.maxHeight;
if (listHeight != null && parentHeight != null) {
setState(() {
_maxChildHeight = (listHeight + 150) / parentHeight;
});
}
}
}
@override
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => updateMaxHeight());
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => Navigator.of(context).pop(),
child: Container(
color: const Color.fromRGBO(0, 0, 0, 0.001),
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
_parentConstraints = constraints;
return GestureDetector(
onTap: () {},
child: DraggableScrollableSheet(
initialChildSize: _maxChildHeight,
minChildSize: 0.1,
maxChildSize: _maxChildHeight,
builder: (_, controller) {
return Container(
color: Colors.grey.shade100,
margin: const EdgeInsets.only(
bottom: kBottomNavigationBarHeight),
child: Column(
children: [
const Align(
alignment: Alignment.topRight,
child: CloseButton(),
),
Flexible(
child: NotificationListener<OverscrollIndicatorNotification>(
onNotification: (OverscrollIndicatorNotification overscroll) {
overscroll.disallowIndicator();
return true;
},
child: _EventModalContent(
key: _key,
controller: controller,
event: widget.event,
),
),
),
],
),
);
}
),
);
}
),
),
);
}
}
class _EventModalContent extends StatelessWidget {
final ScrollController controller;
final Event event;
const _EventModalContent({
required this.controller,
required this.event,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView(
shrinkWrap: true,
padding: const EdgeInsets.symmetric(horizontal: 40),
controller: controller,
children: <Widget>[
// Title
Text(
event.title,
style: Theme.of(context).textTheme.headline1,
),
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),
],
)),
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,
),
),
],
),
]
],
);
}
}

View File

@ -1,97 +0,0 @@
import 'package:flutter/material.dart';
import 'package:furman_now/src/services/events/event.dart';
import 'package:furman_now/src/utils/theme.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl/intl.dart';
class EventCard extends StatelessWidget {
const EventCard
(
this.event,
{
Key? key
}
) : super(key: key);
final Event event;
String get eventHour {
var formatter = DateFormat('hh:mm');
return formatter.format(event.time);
}
String get eventAmPm {
var formatter = DateFormat('a');
return formatter.format(event.time);
}
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
color: Color(0xfff9f9fb),
borderRadius: BorderRadius.all(Radius.circular(10))
),
child: IntrinsicHeight(
child: Row(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(eventHour, style: furmanTextStyle(const TextStyle(fontWeight: FontWeight.w700))),
Text(eventAmPm, style: Theme.of(context).textTheme.subtitle2),
],
),
),
VerticalDivider(
width: 2,
thickness: 2,
color: Colors.grey[200],
),
Flexible(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(event.title, style: furmanTextStyle(const TextStyle(fontWeight: FontWeight.w600))),
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),
],
)),
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),
],
)),
],
),
),
),
],
),
),
);
}
}