import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; import '../../../state/app/infrastructure/loadableState/loadable_state.dart'; import '../../../state/app/infrastructure/loadableState/view/loadable_state_consumer.dart'; import '../../../state/app/infrastructure/utilityWidgets/bloc_module.dart'; import '../../../state/app/modules/marianumDates/bloc/marianum_dates_bloc.dart'; import '../../../state/app/modules/marianumDates/bloc/marianum_dates_event.dart'; import '../../../state/app/modules/marianumDates/bloc/marianum_dates_state.dart'; import '../../../widget/animated_time.dart'; import '../../../widget/centered_leading.dart'; import '../../../widget/debug/debug_tile.dart'; import '../../../widget/list_view_util.dart'; import '../timetable/custom_events/custom_event_edit_dialog.dart'; class MarianumDatesView extends StatelessWidget { const MarianumDatesView({super.key}); @override Widget build(BuildContext context) => BlocModule>( create: (context) => MarianumDatesBloc(), autoRebuild: true, child: (context, bloc, state) => Scaffold( appBar: AppBar( title: const Text('Marianum Termine'), actions: [ PopupMenuButton( initialValue: bloc.showPastEvents(), icon: const Icon(Icons.history), itemBuilder: (context) => [true, false].map((e) => PopupMenuItem( value: e, enabled: e != bloc.showPastEvents(), child: Row( children: [ Icon(e ? Icons.history_outlined : Icons.history_toggle_off_outlined, color: Theme.of(context).colorScheme.onSurface), const SizedBox(width: 15), Text(e ? 'Alle anzeigen' : 'Nur zukünftige anzeigen'), ], ), )).toList(), onSelected: (e) => bloc.add(SetPastEventsVisible(e)), ), ], ), body: LoadableStateConsumer( child: (state, loading) => ListViewUtil.fromList(bloc.getEvents(), (event) => _MarianumDateTile(event: event)), ), ), ); } class _MarianumDateTile extends StatelessWidget { final MarianumDate event; const _MarianumDateTile({required this.event}); String _formatSubtitle() { final start = Jiffy.parseFromDateTime(event.start); final end = Jiffy.parseFromDateTime(event.end); if (event.isAllDay) { // iCal end is exclusive for multi-day all-day events. The feed sets // DTSTART == DTEND for single-day all-day events, so only subtract a // day when end actually advances past start. final inclusiveEnd = event.end.isAfter(event.start) ? end.subtract(days: 1) : end; final sameAllDay = start.format(pattern: 'yyyy-MM-dd') == inclusiveEnd.format(pattern: 'yyyy-MM-dd'); return sameAllDay ? '${start.format(pattern: 'dd.MM.yyyy')} · Ganztägig' : '${start.format(pattern: 'dd.MM.yyyy')} – ${inclusiveEnd.format(pattern: 'dd.MM.yyyy')} · Ganztägig'; } final sameDay = start.format(pattern: 'yyyy-MM-dd') == end.format(pattern: 'yyyy-MM-dd'); if (sameDay) { if (event.start == event.end) { return '${start.format(pattern: 'dd.MM.yyyy')} · ${start.format(pattern: 'HH:mm')}'; } return '${start.format(pattern: 'dd.MM.yyyy')} · ${start.format(pattern: 'HH:mm')} – ${end.format(pattern: 'HH:mm')}'; } return '${start.format(pattern: 'dd.MM.yyyy HH:mm')} – ${end.format(pattern: 'dd.MM.yyyy HH:mm')}'; } @override Widget build(BuildContext context) => ListTile( leading: const CenteredLeading(Icon(Icons.event)), title: Text(event.title.isEmpty ? '(ohne Titel)' : event.title), subtitle: Text(_formatSubtitle()), onTap: () => _showDetails(context), trailing: IconButton( icon: const Icon(Icons.add_circle_outline), tooltip: 'In Stundenplan übernehmen', onPressed: () => showDialog( context: context, builder: (_) => CustomEventEditDialog( initialTitle: event.title, initialDescription: event.description, initialStart: event.start, initialEnd: event.end, ), barrierDismissible: false, ), ), ); void _showDetails(BuildContext context) { showDialog( context: context, builder: (context) => SimpleDialog( title: Text(event.title.isEmpty ? '(ohne Titel)' : event.title), children: [ ListTile( leading: const CenteredLeading(Icon(Icons.date_range_outlined)), title: Text(_formatSubtitle()), ), if (event.description != null && event.description!.trim().isNotEmpty) ListTile( leading: const CenteredLeading(Icon(Icons.notes_outlined)), title: Text(event.description!.trim()), ), Visibility( visible: !event.start.difference(DateTime.now()).isNegative, replacement: ListTile( leading: const CenteredLeading(Icon(Icons.content_paste_search_outlined)), title: Text(Jiffy.parseFromDateTime(event.start).fromNow()), ), child: ListTile( leading: const CenteredLeading(Icon(Icons.timer_outlined)), title: AnimatedTime(callback: () => event.start.difference(DateTime.now())), subtitle: Text(Jiffy.parseFromDateTime(event.start).fromNow()), ), ), DebugTile(context).jsonData(event.toJson()), ], ), ); } }