cofi/lib/event.config.ts

192 lines
5.9 KiB
TypeScript

/**
* Centralized event configuration for CoFi registration.
*
* All event-specific values (pricing, dates, accommodation, branding)
* live here instead of being scattered across components and API routes.
* To adapt this app for a new event, edit this file only.
*/
// ── Event basics ──────────────────────────────────────────────────
export const EVENT_NAME = "CoFi"
export const EVENT_FULL_NAME = "Collaborative Finance"
export const EVENT_YEAR = 2026
export const EVENT_TAGLINE = "Reimagining finance for the commons"
export const EVENT_DATES = "TBD, 2026"
export const EVENT_LOCATION = "TBD"
export const EVENT_SHORT = `${EVENT_NAME} ${EVENT_YEAR}`
// ── Ticket pricing tiers (EUR) ────────────────────────────────────
interface PricingTier {
label: string
price: number
/** Tier is active if today < cutoff date (ISO string, exclusive) */
cutoff: string
}
export const PRICING_TIERS: PricingTier[] = [
{ label: "Early bird", price: 80, cutoff: "2026-04-01" },
{ label: "Regular", price: 120, cutoff: "2026-07-01" },
{ label: "Late", price: 150, cutoff: "2099-12-31" },
]
/** Returns the currently active pricing tier based on today's date */
export function getCurrentTier(): PricingTier {
const now = new Date().toISOString().slice(0, 10)
return PRICING_TIERS.find((t) => now < t.cutoff) ?? PRICING_TIERS[PRICING_TIERS.length - 1]
}
/** Human-readable pricing summary for display */
export function getPricingSummary(): string {
return PRICING_TIERS.map((t) => `${t.price} ${t.label}`).join(" · ")
}
// ── Processing fee ────────────────────────────────────────────────
export const PROCESSING_FEE_PERCENT = 0.02 // 2% to cover Mollie fees
// ── Accommodation ─────────────────────────────────────────────────
export interface AccommodationOption {
id: string
label: string
price: number
nightlyRate: number
venue: string
venueKey: string
description?: string
}
export interface AccommodationVenue {
key: string
name: string
description: string
options: AccommodationOption[]
}
export const ACCOMMODATION_VENUES: AccommodationVenue[] = [
{
key: "venue-a",
name: "Venue A",
description: "TBD — Primary event venue accommodation.",
options: [
{
id: "va-shared",
label: "Bed in shared room",
price: 280,
nightlyRate: 40,
venue: "Venue A",
venueKey: "venue-a",
},
{
id: "va-double",
label: "Bed in double room",
price: 350,
nightlyRate: 50,
venue: "Venue A",
venueKey: "venue-a",
},
],
},
{
key: "venue-b",
name: "Venue B",
description: "TBD — Secondary accommodation option.",
options: [
{
id: "vb-single",
label: "Single room",
price: 560,
nightlyRate: 80,
venue: "Venue B",
venueKey: "venue-b",
},
{
id: "vb-double",
label: "Double room (per person)",
price: 350,
nightlyRate: 50,
venue: "Venue B",
venueKey: "venue-b",
},
],
},
]
/** Flat map of accommodation ID → option for quick lookup */
export const ACCOMMODATION_MAP: Record<string, AccommodationOption> = Object.fromEntries(
ACCOMMODATION_VENUES.flatMap((v) => v.options.map((o) => [o.id, o]))
)
/** Number of nights (used in display) */
export const ACCOMMODATION_NIGHTS = 7
// ── Booking sheet criteria (maps accommodation IDs to bed search criteria) ──
export interface BookingCriteria {
venue: string
bedTypes: string[]
roomFilter?: (room: string) => boolean
}
/**
* Map accommodation option IDs to booking sheet search criteria.
* Update this when you configure the actual booking spreadsheet.
*/
export const BOOKING_CRITERIA: Record<string, BookingCriteria> = {
"va-shared": {
venue: "Venue A",
bedTypes: ["bunk up", "bunk down", "single"],
},
"va-double": {
venue: "Venue A",
bedTypes: ["double", "double (shared)"],
},
"vb-single": {
venue: "Venue B",
bedTypes: ["double"],
},
"vb-double": {
venue: "Venue B",
bedTypes: ["single", "double (shared)"],
},
}
// ── Form field toggles ────────────────────────────────────────────
export const FORM_FIELDS = {
dietary: true,
howHeard: true,
crewConsent: true,
wantFood: true,
}
// ── Email branding ────────────────────────────────────────────────
export const EMAIL_BRANDING = {
primaryColor: "#2563eb", // blue-600
accentColor: "#0d9488", // teal-600
headerText: "You're In!",
taglineColor: "#1e40af", // blue-800
highlightBg: "#eff6ff", // blue-50
highlightBorder: "#2563eb", // blue-600
fromDefault: `${EVENT_NAME} <newsletter@cofi.example.com>`,
internalNotifyDefault: "team@cofi.example.com",
}
// ── External links ────────────────────────────────────────────────
export const LINKS = {
website: "https://cofi.example.com",
telegram: "https://t.me/cofi_example",
community: "https://t.me/cofi_community",
contactEmail: "team@cofi.example.com",
}
// ── Payment description template ──────────────────────────────────
export function buildPaymentDescription(parts: string[]): string {
return `${EVENT_SHORT} Registration — ${parts.join(" + ")}`
}