Files
Client/lib/view/pages/timetable/details/custom_event_sheet.dart
T

132 lines
4.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:rrule/rrule.dart';
import '../../../../api/mhsl/custom_timetable_event/custom_timetable_event.dart';
import '../../../../extensions/date_time.dart';
import '../../../../state/app/modules/timetable/bloc/timetable_bloc.dart';
import '../../../../widget/centered_leading.dart';
import '../../../../widget/debug/debug_tile.dart';
import '../../../../widget/details_bottom_sheet.dart';
import '../custom_events/custom_event_edit_dialog.dart';
import '../data/rrule_with_exceptions.dart';
import '../subject_colors/subject_color_picker.dart';
import 'delete_custom_event.dart';
class CustomEventSheet {
static void show(BuildContext context, CustomTimetableEvent event) {
final timeRange = event.startDate.timeRangeTo(event.endDate);
final bloc = context.read<TimetableBloc>();
showDetailsBottomSheet(
context,
header: ListTile(
leading: const Icon(Icons.event_outlined, size: 32),
title: Text(
event.title,
style: const TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(timeRange),
trailing: TimetableColorHeaderButton(
initialColorName: event.color,
pickerTitle: 'Farbe wählen',
onSelected: (option) =>
bloc.updateCustomEvent(event.id, _withColor(event, option.name)),
),
),
children: (sheetCtx) => [
Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Center(
child: Wrap(
children: [
TextButton.icon(
onPressed: () {
Navigator.of(sheetCtx).pop();
showDialog(
context: context,
builder: (_) =>
CustomEventEditDialog(existingEvent: event),
);
},
label: const Text('Bearbeiten'),
icon: const Icon(Icons.edit_outlined),
),
TextButton.icon(
onPressed: () {
showDeleteCustomEventDialog(context, event).future.then((
_,
) {
if (!sheetCtx.mounted) return;
Navigator.of(sheetCtx).pop();
});
},
label: const Text('Löschen'),
icon: const Icon(Icons.delete_outline),
),
],
),
),
),
const Divider(height: 1),
ListTile(
leading: const Icon(Icons.info_outline),
title: Text(
event.description.isEmpty
? 'Keine Beschreibung'
: event.description,
),
),
ListTile(
leading: const CenteredLeading(Icon(Icons.repeat_outlined)),
title: Text(
'Serie: ${event.rrule.isNotEmpty ? "Wiederholend" : "Einmalig"}',
),
subtitle: FutureBuilder(
future: RruleL10nEn.create(),
builder: (_, snapshot) {
if (event.rrule.isEmpty) {
return const Text('Keine weiteren Vorkommnisse');
}
if (snapshot.data == null) return const Text('...');
// Strip the rrule_generator-specific `;EXDATE=…` suffix
// first — `package:rrule` is strict and throws on it.
final parsed = parseRRuleWithExceptions(event.rrule);
if (parsed.rule.isEmpty) {
return const Text('Keine weiteren Vorkommnisse');
}
final rrule = RecurrenceRule.fromString(parsed.rule);
if (!rrule.canFullyConvertToText) {
return const Text('Keine genauere Angabe möglich.');
}
return Text(rrule.toText(l10n: snapshot.data!));
},
),
),
DebugTile(sheetCtx).child(
ListTile(
leading: const CenteredLeading(Icon(Icons.rule)),
title: const Text('RRule'),
subtitle: Text(event.rrule.isEmpty ? 'Keine' : event.rrule),
),
),
DebugTile(sheetCtx).jsonData(event.toJson()),
],
);
}
static CustomTimetableEvent _withColor(CustomTimetableEvent e, String color) =>
CustomTimetableEvent(
id: e.id,
title: e.title,
description: e.description,
startDate: e.startDate,
endDate: e.endDate,
color: color,
rrule: e.rrule,
skipHolidays: e.skipHolidays,
createdAt: e.createdAt,
updatedAt: DateTime.now(),
);
}