Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions lib/blocs/welcome_cubit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class WelcomeState extends Equatable {
final List<FrontpageArticle>? articles;

/// This can only be null when [isLoading] or [hasException] is true.
final List<BaseEvent>? upcomingEvents;
final List<BaseEvent>? events;

/// This can only be null when [isLoading] or [hasException] is true.
final List<Announcement>? announcements;
Expand All @@ -30,14 +30,14 @@ class WelcomeState extends Equatable {
bool get hasResults =>
slides != null &&
articles != null &&
upcomingEvents != null &&
events != null &&
announcements != null;

@protected
const WelcomeState({
required this.slides,
required this.articles,
required this.upcomingEvents,
required this.events,
required this.announcements,
required this.isLoading,
required this.message,
Expand All @@ -47,7 +47,7 @@ class WelcomeState extends Equatable {
List<Object?> get props => [
slides,
articles,
upcomingEvents,
events,
announcements,
message,
isLoading,
Expand All @@ -56,14 +56,14 @@ class WelcomeState extends Equatable {
WelcomeState copyWith({
List<Slide>? slides,
List<FrontpageArticle>? articles,
List<BaseEvent>? upcomingEvents,
List<BaseEvent>? events,
List<Announcement>? announcements,
bool? isLoading,
String? message,
}) => WelcomeState(
slides: slides ?? this.slides,
articles: articles ?? this.articles,
upcomingEvents: upcomingEvents ?? this.upcomingEvents,
events: events ?? this.events,
announcements: announcements ?? this.announcements,
isLoading: isLoading ?? this.isLoading,
message: message ?? this.message,
Expand All @@ -72,23 +72,23 @@ class WelcomeState extends Equatable {
const WelcomeState.result({
required List<Slide> this.slides,
required List<FrontpageArticle> this.articles,
required List<BaseEvent> this.upcomingEvents,
required List<BaseEvent> this.events,
required List<Announcement> this.announcements,
}) : message = null,
isLoading = false;

const WelcomeState.loading({
this.slides,
this.articles,
this.upcomingEvents,
this.events,
this.announcements,
}) : message = null,
isLoading = true;

const WelcomeState.failure({required String this.message})
: slides = null,
articles = null,
upcomingEvents = null,
events = null,
announcements = null,
isLoading = false;
}
Expand Down Expand Up @@ -137,7 +137,7 @@ class WelcomeCubit extends Cubit<WelcomeState> {
WelcomeState.result(
slides: slides,
articles: articlesResponse.results,
upcomingEvents: events,
events: events,
announcements: announcementsResponse,
),
);
Expand Down
166 changes: 98 additions & 68 deletions lib/ui/screens/welcome_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,6 @@ class WelcomeScreen extends StatefulWidget {
}

class _WelcomeScreenState extends State<WelcomeScreen> {
static final dateFormatter = DateFormat('EEEE d MMMM');

static Map<DateTime, List<BaseEvent>> _groupByDay(List<BaseEvent> events) {
return groupBy<BaseEvent, DateTime>(
events,
(event) => DateTime(event.start.year, event.start.month, event.start.day),
);
}

Widget _makeAnnouncements(List<Announcement> announcements) {
return AnimatedSize(
curve: Curves.ease,
Expand Down Expand Up @@ -109,64 +100,6 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
);
}

Widget _makeUpcomingEvents(List<BaseEvent> events) {
final dayGroupedEvents = _groupByDay(events);
return AnimatedSize(
curve: Curves.ease,
duration: const Duration(milliseconds: 300),
child: Padding(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'UPCOMING EVENTS',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium,
),
...dayGroupedEvents.entries.map<Widget>((entry) {
final now = DateTime.now();
final today = DateTime(now.year, now.month, now.day);
final day = entry.key;
final dayEvents = entry.value;
String dayText;
switch (day.difference(today).inDays) {
case 0:
dayText = 'TODAY';
break;
case 1:
dayText = 'TOMORROW';
break;
default:
dayText = dateFormatter.format(day).toUpperCase();
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 8),
Text(
dayText,
textAlign: TextAlign.left,
style: Theme.of(context).textTheme.bodySmall,
),
for (final event in dayEvents) EventDetailCard(event: event),
],
);
}),
if (events.isEmpty)
const Padding(
padding: EdgeInsets.all(8),
child: Text(
'There are no upcoming events.',
textAlign: TextAlign.center,
),
),
],
),
),
);
}

@override
Widget build(BuildContext context) {
return Scaffold(
Expand Down Expand Up @@ -194,7 +127,8 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
_makeArticles(state.articles!),
if (state.articles!.isNotEmpty)
const Divider(indent: 16, endIndent: 16, height: 8),
_makeUpcomingEvents(state.upcomingEvents!),
// _makeEvents(state.events!),
Events(state.events!),
TextButton(
onPressed: () => context.goNamed('calendar'),
child: const Text('SHOW THE ENTIRE AGENDA'),
Expand Down Expand Up @@ -281,6 +215,102 @@ class _SlidesCarouselState extends State<SlidesCarousel> {
}
}

class Events extends StatelessWidget {
const Events(this.events);
final List<BaseEvent>? events;

static final dateFormatter = DateFormat('EEEE d MMMM');
static Map<DateTime, List<BaseEvent>> _groupByDay(List<BaseEvent> events) {
return groupBy<BaseEvent, DateTime>(
events,
(event) => DateTime(event.start.year, event.start.month, event.start.day),
);
}

@override
Widget build(BuildContext context) {
final now = DateTime.now();

bool isOngoing(BaseEvent event) =>
event.start.isBefore(now) && event.end.isAfter(now);

final ongoingEvents = events!.where((e) => isOngoing(e)).toList();
final upcomingEvents = events!.where((e) => !isOngoing(e)).toList();
return Column(
children: [
if (ongoingEvents.isNotEmpty)
_makeEventsSection(context, ongoingEvents, 'ONGOING EVENTS', false),
_makeEventsSection(context, upcomingEvents, 'UPCOMING EVENTS', true),
],
);
}

Widget _makeEventsSection(
BuildContext context,
List<BaseEvent> events,
String title,
bool showDayText,
) {
final dayGroupedEvents = _groupByDay(events);
return AnimatedSize(
curve: Curves.ease,
duration: const Duration(milliseconds: 300),
child: Padding(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
title,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium,
),
...dayGroupedEvents.entries.map<Widget>((entry) {
final now = DateTime.now();
final today = DateTime(now.year, now.month, now.day);
final day = entry.key;
final dayEvents = entry.value;
String dayText;
switch (day.difference(today).inDays) {
case 0:
dayText = 'TODAY';
break;
case 1:
dayText = 'TOMORROW';
break;
default:
dayText = dateFormatter.format(day).toUpperCase();
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (showDayText) SizedBox(height: 8),
if (showDayText)
Text(
dayText,
// dateFormatter.format(day).toUpperCase(),
textAlign: TextAlign.left,
style: Theme.of(context).textTheme.bodySmall,
),
for (final event in dayEvents) EventDetailCard(event: event),
],
);
}),
if (events.isEmpty)
const Padding(
padding: EdgeInsets.all(8),
child: Text(
'There are no events here.',
textAlign: TextAlign.center,
),
),
],
),
),
);
}
}

class Announcements extends StatefulWidget {
final List<Announcement> announcements;

Expand Down
16 changes: 14 additions & 2 deletions lib/ui/widgets/event_detail_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:reaxit/ui/theme.dart';

class EventDetailCard extends StatelessWidget {
static final timeFormatter = DateFormat('HH:mm');
static final dateFormatter = DateFormat('dd/MM HH:mm');
final BaseEvent event;
final Color _indicatorColor;
final bool _hasFoodEvent;
Expand Down Expand Up @@ -53,8 +54,19 @@ class EventDetailCard extends StatelessWidget {
PartnerEvent _ => Colors.black,
_ => null,
};
final start = timeFormatter.format(event.start.toLocal());
final end = timeFormatter.format(event.end.toLocal());
String start = timeFormatter.format(event.start.toLocal());
String end = timeFormatter.format(event.end.toLocal());

final startDate = event.start.toLocal();
final endDate = event.end.toLocal();

if (startDate.day != endDate.day ||
startDate.month != endDate.month ||
startDate.year != endDate.year) {
// Event takes more than a day, show date as well
start = dateFormatter.format(startDate);
end = dateFormatter.format(endDate);
}

// Remove HTML tags.
final caption = event.caption.replaceAll(RegExp(r'<[^>]*>|&[^;]+;'), '');
Expand Down
2 changes: 1 addition & 1 deletion test/widget/welcome_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void main() {
final state = WelcomeState.result(
slides: const [],
articles: const [],
upcomingEvents: [normalEvent, partnerEvent],
events: [normalEvent, partnerEvent],
announcements: const [],
);

Expand Down
Loading