Files
Artista-Filmcamp/src/lib/camp.ts
T
Nick SzaunigandClaude Opus 5.5 7203cd1e6e feat: Onepage nach Filmcamp-Gliederung umgebaut
- Figtree als einzige Schrift, Logo mittig in fester Kopfzeile
- Headerbild ueber volle Breite und Hoehe, ohne Preis, mit Terminleiste
- "Was dich erwartet" stellt die Villa mit animierter Bilderfolge vor,
  darunter Tagesablauf als Karussell (Programm folgt als PDF)
- Preis: regulaerer Preis durchgestrichen, kein Verkaufsstartdatum,
  Ueberschrift "Jetzt Platz sichern mit Early Bird"
- Team als "Mit dabei", danach drei Reels im Hochformat
- Logo, Headerbild, Portraets und Reels ueber feste Dateinamen im
  Medienverzeichnis (docs/MEDIEN.md), ohne Neustart austauschbar
- Widerrufsbelehrung im Admin pflegbar, Seite /widerruf, Live-Verkauf
  ohne Freigabe gesperrt
- Anreise: Abholung am Bahnhof Firenze Santa Maria Novella
- Booking-Link entfernt, Gedankenstriche aus Kundentexten entfernt

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-01 23:53:18 +02:00

93 lines
3.7 KiB
TypeScript

import type { Camp } from "@/generated/prisma/client";
import { CAMP_ID, type Db, type Tx } from "./db";
import { evaluateSales, type CampGateFields, type SalesState, type StripeMode } from "./sales-gate";
import { dbDateToIso } from "./time";
/**
* Laedt die Camp-Konfiguration. Fehlt die Zeile (frische Datenbank), wird
* sie mit sicheren Standardwerten angelegt: Live-Verkauf aus, keine
* Freigaben, 13 Plaetze und 4 Stammmodel-Buchungen. Die Migration
* 20261001120000_camp_2027_bestaetigt legt Termin, Ort und Zimmer fest.
*/
export async function getCamp(db: Db | Tx): Promise<Camp> {
return db.camp.upsert({ where: { id: CAMP_ID }, create: { id: CAMP_ID }, update: {} });
}
export function campStartIso(camp: Pick<Camp, "campStartDate">): string | null {
return camp.campStartDate ? dbDateToIso(camp.campStartDate) : null;
}
export function toGateFields(camp: Camp): CampGateFields {
return {
salesEnabled: camp.salesEnabled,
capacityConfirmed: camp.capacityConfirmed,
stammmodelQuotaConfirmed: camp.stammmodelQuotaConfirmed,
campStartDate: campStartIso(camp),
dateConfirmed: camp.dateConfirmed,
locationName: camp.locationName,
locationConfirmed: camp.locationConfirmed,
accommodationText: camp.accommodationText,
accommodationConfirmed: camp.accommodationConfirmed,
servicesConfirmed: camp.servicesConfirmed,
organizerName: camp.organizerName,
organizerAddress: camp.organizerAddress,
organizerEmail: camp.organizerEmail,
organizerConfirmed: camp.organizerConfirmed,
taxNote: camp.taxNote,
taxConfirmed: camp.taxConfirmed,
termsVersion: camp.termsVersion,
termsApproved: camp.termsApproved,
withdrawalText: camp.withdrawalText,
withdrawalApproved: camp.withdrawalApproved,
travelLawChecked: camp.travelLawChecked,
installmentsApproved: camp.installmentsApproved,
installmentRuleApproved: camp.installmentRuleApproved,
testPhaseOverride: camp.testPhaseOverride,
};
}
export function salesStateFor(camp: Camp, mode: StripeMode, now: Date = new Date()): SalesState {
return evaluateSales(now, toGateFields(camp), mode);
}
/**
* Oeffentlich anzeigbare, bestaetigte Fakten. Unbestaetigte Werte werden
* hier bewusst zu null — die Seite zeigt dann "wird bekanntgegeben" statt
* eines ungeprueften Datums oder Orts.
*/
export type PublicCampFacts = {
startDate: string | null;
endDate: string | null;
location: string | null;
region: string | null;
accommodationText: string | null;
taxNote: string | null;
organizer: { name: string; address: string; email: string; phone: string | null } | null;
termsUrl: string | null;
termsVersion: string | null;
withdrawalText: string | null;
};
export function publicCampFacts(camp: Camp): PublicCampFacts {
return {
startDate: camp.dateConfirmed ? campStartIso(camp) : null,
endDate: camp.dateConfirmed && camp.campEndDate ? dbDateToIso(camp.campEndDate) : null,
location: camp.locationConfirmed ? camp.locationName : null,
region: camp.locationConfirmed ? camp.locationRegion : null,
accommodationText: camp.accommodationConfirmed ? camp.accommodationText : null,
taxNote: camp.taxConfirmed ? camp.taxNote : null,
organizer:
camp.organizerConfirmed && camp.organizerName && camp.organizerAddress && camp.organizerEmail
? {
name: camp.organizerName,
address: camp.organizerAddress,
email: camp.organizerEmail,
phone: camp.organizerPhone,
}
: null,
termsUrl: camp.termsApproved ? camp.termsUrl : null,
termsVersion: camp.termsApproved ? camp.termsVersion : null,
withdrawalText: camp.withdrawalApproved ? camp.withdrawalText : null,
};
}