# Feature: Kalender **Filsti:** `docs/features/kalender.md` ## 1. Konsept Månedsbasert kalendervisning for redaksjonell planlegging. Hendelser er nodes i kunnskapsgrafen og kan kobles til episoder, temaer, aktører og kanban-kort. Komplementerer Kanban ("hva" vs "når"). ## 2. Status **PG-adapter ferdig og deployet (mars 2025).** Abonnement, ICS-eksport og SpacetimeDB-sync gjenstår. ### Implementert - Migrering `0003_calendar.sql`: `calendars` + `calendar_events` (begge FK→nodes) - Hendelser er nodes — arver workspace-isolasjon automatisk - Heldagshendelser (`T12:00:00` for tidssone-trygghet) vs. tidshendelser med klokkeslett - Fargekoder per hendelse (7 forhåndsdefinerte) + standard kalenderfarge - REST API: GET med tidsvindu-filtrering, POST/PATCH/DELETE hendelser - PG polling-adapter med 5 sek intervall - CalendarBlock.svelte: månedsrutenett, navigering, opprett/rediger-modal, Escape-lukking - `linked_node`-kolonne for fremtidig kobling til kanban-kort, episoder etc. ### Gjenstår — Fase 2 - Kobling til kanban-kort (vis deadline på kalender) - Uke- og dagsvisning - Gjentakende hendelser (RRULE) - Dra-og-slipp for å flytte hendelser mellom datoer - Flerdag-hendelser (vises over flere celler) - Abonnementsmodell (kalender → kalender via graph_edges) - Personlige vs. workspace-kalendere - ICS/CalDAV-eksport - SpacetimeDB-modul + hybrid-adapter - Varsler/påminnelser via jobbkøen ## 3. Datamodell (implementert) ```sql CREATE TABLE calendars ( id UUID PRIMARY KEY REFERENCES nodes(id) ON DELETE CASCADE, parent_id UUID NOT NULL REFERENCES nodes(id), name TEXT NOT NULL, color TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE calendar_events ( id UUID PRIMARY KEY REFERENCES nodes(id) ON DELETE CASCADE, calendar_id UUID NOT NULL REFERENCES calendars(id) ON DELETE CASCADE, title TEXT NOT NULL, description TEXT, starts_at TIMESTAMPTZ NOT NULL, ends_at TIMESTAMPTZ, all_day BOOLEAN NOT NULL DEFAULT false, color TEXT, linked_node UUID REFERENCES nodes(id) ON DELETE SET NULL, created_by TEXT REFERENCES users(authentik_id), created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); ``` Indekser: `(calendar_id)` og `(calendar_id, starts_at)` for effektiv tidsvindu-filtrering. ## 4. API-endepunkter | Metode | Sti | Beskrivelse | |---|---|---| | GET | `/api/calendar/[calendarId]?from=...&to=...` | Hent kalender med hendelser i tidsvindu | | POST | `/api/calendar/[calendarId]/events` | Opprett hendelse | | PATCH | `/api/calendar/[calendarId]/events/[eventId]` | Oppdater hendelse | | DELETE | `/api/calendar/[calendarId]/events/[eventId]` | Slett hendelse | ## 5. Brukes av | Konsept | Bruk | |---|---| | Redaksjonen | Innspillingsdatoer, publiseringsplan, deadlines | | Foreningen Liberalistene | Styremøter, arrangementer | | Møterommet (fremtidig) | Møteplanlegging | ## 6. Tidssone-håndtering - Heldagshendelser lagres som `T12:00:00` (middag) — unngår datoforskyvning ved UTC-konvertering - Tidshendelser konverteres til ISO via `new Date().toISOString()` (lokal → UTC) - Visning bruker `new Date()` som konverterer tilbake til lokal tid ## 7. Fremtidig: Abonnementsmodell Kalendere kan abonnere på andre kalendere via `SUBSCRIBES_TO`-edge i grafen. Abonnenten ser hendelser read-only. | Type | Eier | Synlighet | |------|------|-----------| | Workspace | Workspace (admin) | Alle medlemmer | | Personlig | Bruker | Kun eier + eksplisitt deling | | Offentlig | Workspace | Alle som abonnerer | ## 8. Fremtidig: ICS-eksport Offentlige kalendere får en ICS-URL (`/cal/{workspace_slug}/{calendar_id}.ics`) for Google Calendar, Apple Calendar etc. ## 9. Instruks for Claude Code * Bruk `eventsForDate()` med lokal dato-konvertering, ikke UTC-substring * Heldagshendelser: `T12:00:00`, aldri `T00:00:00` (tidssone-felle) * Alt er workspace-scopet via node-modellen * Sjekk `docs/erfaringer/adapter_moenster.md` for hybrid-strategi