Add multi calendar support and protected web app
This commit is contained in:
+101
-1
@@ -72,6 +72,9 @@ class CalendarPage extends StatefulWidget {
|
||||
required this.weather,
|
||||
required this.onAdd,
|
||||
required this.onEdit,
|
||||
this.title,
|
||||
this.secondaryEvents = const [],
|
||||
this.appCalendars = const [],
|
||||
this.onAssignPerson,
|
||||
});
|
||||
|
||||
@@ -80,6 +83,9 @@ class CalendarPage extends StatefulWidget {
|
||||
final WeatherSnapshot? weather;
|
||||
final VoidCallback onAdd;
|
||||
final ValueChanged<CalendarEvent> onEdit;
|
||||
final String? title;
|
||||
final List<CalendarEvent> secondaryEvents;
|
||||
final List<AppCalendar> appCalendars;
|
||||
final void Function(CalendarEvent event, Person person)? onAssignPerson;
|
||||
|
||||
@override
|
||||
@@ -139,7 +145,7 @@ class _CalendarPageState extends State<CalendarPage> {
|
||||
return PageFrame(
|
||||
eyebrow:
|
||||
'${formatDate(weekStart)} \u2013 ${formatDate(weekStart.add(const Duration(days: 6)))}',
|
||||
title: '${isoWeekNumber(weekStart)}. h\u00e9t',
|
||||
title: widget.title ?? '${isoWeekNumber(weekStart)}. h\u00e9t',
|
||||
action: FilledButton.icon(
|
||||
onPressed: widget.onAdd,
|
||||
icon: const Icon(Icons.add),
|
||||
@@ -184,6 +190,8 @@ class _CalendarPageState extends State<CalendarPage> {
|
||||
onSelectDay: _selectDay,
|
||||
onPreviousWeek: () => _moveWeek(-1),
|
||||
onNextWeek: () => _moveWeek(1),
|
||||
secondaryEvents: widget.secondaryEvents,
|
||||
appCalendars: widget.appCalendars,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
DayDetailsPanel(
|
||||
@@ -213,6 +221,8 @@ class _CalendarPageState extends State<CalendarPage> {
|
||||
onSelectDay: _selectDay,
|
||||
onPreviousWeek: () => _moveWeek(-1),
|
||||
onNextWeek: () => _moveWeek(1),
|
||||
secondaryEvents: widget.secondaryEvents,
|
||||
appCalendars: widget.appCalendars,
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
DayDetailsPanel(
|
||||
@@ -666,6 +676,8 @@ class WeekBoard extends StatelessWidget {
|
||||
required this.onSelectDay,
|
||||
required this.onPreviousWeek,
|
||||
required this.onNextWeek,
|
||||
this.secondaryEvents = const [],
|
||||
this.appCalendars = const [],
|
||||
});
|
||||
|
||||
final List<CalendarEvent> events;
|
||||
@@ -675,6 +687,8 @@ class WeekBoard extends StatelessWidget {
|
||||
final ValueChanged<int> onSelectDay;
|
||||
final VoidCallback onPreviousWeek;
|
||||
final VoidCallback onNextWeek;
|
||||
final List<CalendarEvent> secondaryEvents;
|
||||
final List<AppCalendar> appCalendars;
|
||||
|
||||
static const days = [
|
||||
'H\u00e9tf\u0151',
|
||||
@@ -736,6 +750,9 @@ class WeekBoard extends StatelessWidget {
|
||||
.where((event) => isSameDate(event.date, date))
|
||||
.toList()
|
||||
..sort((a, b) => a.start.compareTo(b.start));
|
||||
final daySecondaryEvents = secondaryEvents
|
||||
.where((event) => isSameDate(event.date, date))
|
||||
.toList();
|
||||
return Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: index == 6 ? 0 : 6),
|
||||
@@ -744,6 +761,8 @@ class WeekBoard extends StatelessWidget {
|
||||
dateLabel: formatShortDate(date),
|
||||
active: selectedDay == index,
|
||||
events: dayEvents,
|
||||
secondaryEvents: daySecondaryEvents,
|
||||
appCalendars: appCalendars,
|
||||
people: people,
|
||||
onTap: () => onSelectDay(index),
|
||||
),
|
||||
@@ -765,6 +784,8 @@ class WeekDayColumn extends StatelessWidget {
|
||||
required this.dateLabel,
|
||||
required this.active,
|
||||
required this.events,
|
||||
required this.secondaryEvents,
|
||||
required this.appCalendars,
|
||||
required this.people,
|
||||
required this.onTap,
|
||||
});
|
||||
@@ -773,6 +794,8 @@ class WeekDayColumn extends StatelessWidget {
|
||||
final String dateLabel;
|
||||
final bool active;
|
||||
final List<CalendarEvent> events;
|
||||
final List<CalendarEvent> secondaryEvents;
|
||||
final List<AppCalendar> appCalendars;
|
||||
final List<Person> people;
|
||||
final VoidCallback onTap;
|
||||
|
||||
@@ -839,6 +862,13 @@ class WeekDayColumn extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
if (secondaryEvents.isNotEmpty) ...[
|
||||
CalendarDayIndicatorStrip(
|
||||
events: secondaryEvents,
|
||||
appCalendars: appCalendars,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
if (events.isEmpty)
|
||||
const SizedBox(
|
||||
height: 92,
|
||||
@@ -954,6 +984,76 @@ class WeekEventPill extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class CalendarDayIndicatorStrip extends StatelessWidget {
|
||||
const CalendarDayIndicatorStrip({
|
||||
super.key,
|
||||
required this.events,
|
||||
required this.appCalendars,
|
||||
});
|
||||
|
||||
final List<CalendarEvent> events;
|
||||
final List<AppCalendar> appCalendars;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final calendarIds = events
|
||||
.map((event) => event.appCalendarId)
|
||||
.whereType<String>()
|
||||
.toSet()
|
||||
.toList();
|
||||
return Wrap(
|
||||
spacing: 4,
|
||||
runSpacing: 4,
|
||||
children: calendarIds.take(3).map((id) {
|
||||
final calendar = appCalendars.firstWhere(
|
||||
(item) => item.id == id,
|
||||
orElse: () => AppCalendar(
|
||||
id: id,
|
||||
name: 'Napt\u00e1r',
|
||||
colorValue: appCalendarColors.first.toARGB32(),
|
||||
),
|
||||
);
|
||||
return Tooltip(
|
||||
message:
|
||||
'${calendar.name}: ${events.where((event) => event.appCalendarId == id).length} esem\u00e9ny',
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3),
|
||||
decoration: BoxDecoration(
|
||||
color: calendar.color.withValues(alpha: .14),
|
||||
borderRadius: BorderRadius.circular(999),
|
||||
border: Border.all(color: calendar.color.withValues(alpha: .22)),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
width: 6,
|
||||
height: 6,
|
||||
decoration: BoxDecoration(
|
||||
color: calendar.color,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 3),
|
||||
Text(
|
||||
calendar.name,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(
|
||||
color: calendar.color,
|
||||
fontSize: 9,
|
||||
fontWeight: FontWeight.w900,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class MiniAudienceAvatar extends StatelessWidget {
|
||||
const MiniAudienceAvatar({
|
||||
super.key,
|
||||
|
||||
Reference in New Issue
Block a user