marianum appointments

This commit is contained in:
2026-05-05 16:05:07 +02:00
parent e8faa77e70
commit bee5c02a4f
13 changed files with 971 additions and 13 deletions
@@ -17,11 +17,15 @@ class CustomEventEditDialog extends StatefulWidget {
final CustomTimetableEvent? existingEvent;
final DateTime? initialStart;
final DateTime? initialEnd;
final String? initialTitle;
final String? initialDescription;
const CustomEventEditDialog({
this.existingEvent,
this.initialStart,
this.initialEnd,
this.initialTitle,
this.initialDescription,
super.key,
});
@@ -30,15 +34,21 @@ class CustomEventEditDialog extends StatefulWidget {
}
class _CustomEventEditDialogState extends State<CustomEventEditDialog> {
// Visible window of the timetable / time picker (matches `_pickTimeRange`'s
// `disabledTime`). Pre-filled times from outside this window are clamped in.
static const TimeOfDay _windowStart = TimeOfDay(hour: 8, minute: 0);
static const TimeOfDay _windowEnd = TimeOfDay(hour: 16, minute: 30);
static const int _minDurationMinutes = 15;
late DateTime _date = widget.existingEvent?.startDate ?? widget.initialStart ?? DateTime.now();
late TimeOfDay _startTime = widget.existingEvent?.startDate.toTimeOfDay() ??
widget.initialStart?.toTimeOfDay() ??
const TimeOfDay(hour: 8, minute: 0);
late TimeOfDay _endTime = widget.existingEvent?.endDate.toTimeOfDay() ??
widget.initialEnd?.toTimeOfDay() ??
const TimeOfDay(hour: 9, minute: 30);
late final TextEditingController _name = TextEditingController(text: widget.existingEvent?.title);
late final TextEditingController _description = TextEditingController(text: widget.existingEvent?.description);
late TimeOfDay _startTime;
late TimeOfDay _endTime;
late final TextEditingController _name = TextEditingController(
text: widget.existingEvent?.title ?? widget.initialTitle,
);
late final TextEditingController _description = TextEditingController(
text: widget.existingEvent?.description ?? widget.initialDescription,
);
late String _rrule = widget.existingEvent?.rrule ?? '';
late CustomTimetableColors _color = CustomTimetableColors.values.firstWhere(
(e) => e.name == widget.existingEvent?.color,
@@ -47,6 +57,37 @@ class _CustomEventEditDialogState extends State<CustomEventEditDialog> {
bool get _isEditing => widget.existingEvent != null;
@override
void initState() {
super.initState();
if (_isEditing) {
_startTime = widget.existingEvent!.startDate.toTimeOfDay();
_endTime = widget.existingEvent!.endDate.toTimeOfDay();
return;
}
final rawStart = widget.initialStart?.toTimeOfDay() ?? _windowStart;
final rawEnd = widget.initialEnd?.toTimeOfDay() ?? const TimeOfDay(hour: 9, minute: 30);
final clamped = _clampToVisibleWindow(rawStart, rawEnd);
_startTime = clamped.$1;
_endTime = clamped.$2;
}
static (TimeOfDay, TimeOfDay) _clampToVisibleWindow(TimeOfDay rawStart, TimeOfDay rawEnd) {
int toMin(TimeOfDay t) => t.hour * 60 + t.minute;
TimeOfDay fromMin(int m) => TimeOfDay(hour: m ~/ 60, minute: m % 60);
final windowStart = toMin(_windowStart);
final windowEnd = toMin(_windowEnd);
var start = toMin(rawStart).clamp(windowStart, windowEnd - _minDurationMinutes);
var end = toMin(rawEnd);
if (end < start + _minDurationMinutes) end = start + _minDurationMinutes;
if (end > windowEnd) {
end = windowEnd;
start = end - _minDurationMinutes;
}
return (fromMin(start), fromMin(end));
}
bool _validate() => _name.text.isNotEmpty;
void _save() {
@@ -79,11 +120,14 @@ class _CustomEventEditDialogState extends State<CustomEventEditDialog> {
}
Future<void> _pickDate() async {
final now = DateTime.now();
final defaultFirst = now.subtract(const Duration(days: 30));
final defaultLast = now.add(const Duration(days: 365));
final picked = await showDatePicker(
context: context,
initialDate: _date,
firstDate: DateTime.now().subtract(const Duration(days: 30)),
lastDate: DateTime.now().add(const Duration(days: 30)),
firstDate: _date.isBefore(defaultFirst) ? _date : defaultFirst,
lastDate: _date.isAfter(defaultLast) ? _date : defaultLast,
);
if (picked != null && picked != _date) setState(() => _date = picked);
}
+2 -1
View File
@@ -27,7 +27,8 @@ class DefaultSettings {
Modules.marianumMessage,
Modules.roomPlan,
Modules.gradeAveragesCalculator,
Modules.holidays
Modules.holidays,
Modules.marianumDates,
],
hiddenModules: [],
),