Add recurring events, push notifications, config sync — and mobile layout fixes

Recurring event editing (rrule) with this/all occurrence scope, web push
subscriptions (VAPID) with a cached config layer for notification settings,
and email delivery via nodemailer.

Also fixes the calendar view never actually stacking on mobile: the
Calendars filter column used flex:1 with minWidth:0 on its sibling, so
flex-wrap never triggered regardless of viewport width, squeezing the grid
and view switcher into a sliver next to a fixed 220px sidebar. Adds a
proper mobile breakpoint that stacks the layout, scrolls the week grid
horizontally instead of compressing it, and enlarges touch targets.
This commit is contained in:
jtricerolph 2026-07-25 23:04:59 +00:00
parent dad3cc472c
commit ca0dc9b070
28 changed files with 1517 additions and 155 deletions

View file

@ -7,7 +7,7 @@ export default function MonthGrid({ events, date, onSelectDate, onSelectEvent }:
events: EventSummary[]
date: Date
onSelectDate?: (d: Date) => void
onSelectEvent: (id: number) => void
onSelectEvent: (ev: EventSummary) => void
}) {
const days = monthGridDays(date)
const today = new Date()
@ -35,7 +35,7 @@ export default function MonthGrid({ events, date, onSelectDate, onSelectEvent }:
className="cal-event-chip"
style={{ background: ev.calendar_color, color: '#fff' }}
title={ev.title}
onClick={e => { e.stopPropagation(); onSelectEvent(ev.id) }}
onClick={e => { e.stopPropagation(); onSelectEvent(ev) }}
>
{!ev.all_day && `${formatTime(ev.start_at)} `}{ev.title}
</span>