feat: redesign CMS and unify German admin UI
This commit is contained in:
@@ -11,13 +11,13 @@ const WINDOW_FUTURE_MS = 400 * 24 * 60 * 60 * 1000;
|
||||
|
||||
/**
|
||||
* Builds the calendar entries for Anna's personal ICS feed: confirmed
|
||||
* bookings (never pending ones) plus standalone public events — onsite and
|
||||
* bookings (never pending ones) plus standalone public events - onsite and
|
||||
* online alike. Deliberately never includes the meeting password anywhere
|
||||
* in the output, only a link to the protected join page.
|
||||
*
|
||||
* Local API is used with the default overrideAccess: true because this is
|
||||
* only ever reached after the caller already verified the feed's secret
|
||||
* token (see app/(frontend)/calendar/[tokenFile]/route.ts) — equivalent
|
||||
* token (see app/(frontend)/calendar/[tokenFile]/route.ts) - equivalent
|
||||
* trust to the existing admin calendar view.
|
||||
*/
|
||||
export async function getAdminFeedICSEvents(payload: Payload): Promise<ICSEvent[]> {
|
||||
@@ -83,7 +83,7 @@ export async function getAdminFeedICSEvents(payload: Payload): Promise<ICSEvent[
|
||||
end: new Date(b.endTime),
|
||||
summary: offer?.title ?? "Termin",
|
||||
description: description || undefined,
|
||||
// Vor Ort: vollständige Adresse. Online: literal "Online" — never the
|
||||
// Vor Ort: vollständige Adresse. Online: literal "Online" - never the
|
||||
// meeting password, which is intentionally not part of this feed.
|
||||
location: isOnline ? "Online" : fullAddress || undefined,
|
||||
url,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { createHash, randomBytes } from "node:crypto";
|
||||
|
||||
/**
|
||||
* Long-lived, random, rotatable secret for a personal calendar-subscription
|
||||
* URL (/calendar/<token>.ics) — treated like an API key, not a
|
||||
* URL (/calendar/<token>.ics) - treated like an API key, not a
|
||||
* short-lived link: only its hash is stored, so a database leak alone
|
||||
* can't be used to subscribe to anyone's calendar, and rotating it
|
||||
* (overwriting the stored hash) immediately invalidates the old URL.
|
||||
|
||||
@@ -68,7 +68,7 @@ export function berlinDayBounds(date: Date): { key: string; start: Date; end: Da
|
||||
* representation for iCalendar's local `TZID` date-time form
|
||||
* (`DTSTART;TZID=Europe/Berlin:YYYYMMDDTHHMMSS`). Uses the ICU timezone
|
||||
* database via Intl rather than manual UTC+1/+2 arithmetic, so daylight
|
||||
* saving transitions are always handled correctly — no naive UTC offset
|
||||
* saving transitions are always handled correctly - no naive UTC offset
|
||||
* math that would drift by an hour half the year.
|
||||
*/
|
||||
export function toBerlinICSDateTime(date: Date): string {
|
||||
@@ -87,7 +87,7 @@ export function toBerlinICSDateTime(date: Date): string {
|
||||
return `${get("year")}${get("month")}${get("day")}T${get("hour")}${get("minute")}${get("second")}`;
|
||||
}
|
||||
|
||||
/** UTC timestamp form (`YYYYMMDDTHHMMSSZ`) — used only for DTSTAMP, which marks generation time, not a local event time. */
|
||||
/** UTC timestamp form (`YYYYMMDDTHHMMSSZ`) - used only for DTSTAMP, which marks generation time, not a local event time. */
|
||||
export function toUTCICSStamp(date: Date): string {
|
||||
return date.toISOString().replace(/[-:]/g, "").split(".")[0] + "Z";
|
||||
}
|
||||
@@ -95,7 +95,7 @@ export function toUTCICSStamp(date: Date): string {
|
||||
/**
|
||||
* Standard IANA Europe/Berlin VTIMEZONE block (the same one commonly
|
||||
* embedded by calendar exporters): CEST from the last Sunday in March,
|
||||
* CET from the last Sunday in October — the actual EU DST rule, not an
|
||||
* CET from the last Sunday in October - the actual EU DST rule, not an
|
||||
* approximation.
|
||||
*/
|
||||
export const BERLIN_VTIMEZONE_LINES = [
|
||||
|
||||
Reference in New Issue
Block a user