/** * Court Management Types * * Types for club profile and court inventory CRUD operations. */ export interface Court { court_id: number; name: string; sport_variation_id?: number; // For backward compatibility (deprecated) sport_variation?: { sport_variation_id: number; name: string; slug: string; sport: { sport_id: number; name: string; slug: string; }; }; created_at: string; // ISO 8601 timestamp updated_at: string; // ISO 8601 timestamp } export interface CourtRequest { name: string; sport_variation_id: number; } export interface SportVariation { sport_variation_id: number; name: string; slug: string; } export interface Sport { sport_id: number; name: string; slug: string; logo_url: string | null; variations: SportVariation[]; } export interface SportsResponse { sports: Sport[]; } export interface CourtDependencies { court_id: number; can_delete: boolean; dependencies: { slot_definitions: number; slot_instances_future: number; slot_instances_booked: number; }; } export interface ClubProfileSettings { address?: { line_1?: string; line_2?: string; city?: string; postal_code?: string; country?: string; }; contact?: { phone?: string; email?: string; website?: string; }; // Other future settings can be added here [key: string]: any; // Allow arbitrary JSONB data } export interface ClubProfile { club_id: number; name: string; timezone: string; // IANA timezone settings?: ClubProfileSettings; created_at: string; // ISO 8601 timestamp updated_at: string; // ISO 8601 timestamp } export interface ClubProfileUpdateRequest { name?: string; timezone?: string; settings?: ClubProfileSettings; } export interface CourtError { type: string; title: string; status: number; detail: string; code: string; errors?: ValidationError[]; dependencies?: { slot_definitions: number; upcoming_bookings: number; }; } export interface ValidationError { field: string; message: string; } /** * IANA Timezone list (common timezones) * Full list can be expanded as needed */ export const COMMON_TIMEZONES = [ { value: 'Europe/London', label: 'London (GMT/BST)' }, { value: 'Europe/Paris', label: 'Paris (CET/CEST)' }, { value: 'Europe/Berlin', label: 'Berlin (CET/CEST)' }, { value: 'Europe/Madrid', label: 'Madrid (CET/CEST)' }, { value: 'Europe/Rome', label: 'Rome (CET/CEST)' }, { value: 'Europe/Amsterdam', label: 'Amsterdam (CET/CEST)' }, { value: 'Europe/Brussels', label: 'Brussels (CET/CEST)' }, { value: 'Europe/Vienna', label: 'Vienna (CET/CEST)' }, { value: 'Europe/Zurich', label: 'Zurich (CET/CEST)' }, { value: 'Europe/Stockholm', label: 'Stockholm (CET/CEST)' }, { value: 'Europe/Copenhagen', label: 'Copenhagen (CET/CEST)' }, { value: 'Europe/Oslo', label: 'Oslo (CET/CEST)' }, { value: 'Europe/Helsinki', label: 'Helsinki (EET/EEST)' }, { value: 'Europe/Athens', label: 'Athens (EET/EEST)' }, { value: 'Europe/Istanbul', label: 'Istanbul (TRT)' }, { value: 'Europe/Moscow', label: 'Moscow (MSK)' }, { value: 'America/New_York', label: 'New York (EST/EDT)' }, { value: 'America/Chicago', label: 'Chicago (CST/CDT)' }, { value: 'America/Denver', label: 'Denver (MST/MDT)' }, { value: 'America/Los_Angeles', label: 'Los Angeles (PST/PDT)' }, { value: 'America/Toronto', label: 'Toronto (EST/EDT)' }, { value: 'America/Vancouver', label: 'Vancouver (PST/PDT)' }, { value: 'America/Mexico_City', label: 'Mexico City (CST/CDT)' }, { value: 'America/Sao_Paulo', label: 'São Paulo (BRT/BRST)' }, { value: 'America/Buenos_Aires', label: 'Buenos Aires (ART)' }, { value: 'Asia/Dubai', label: 'Dubai (GST)' }, { value: 'Asia/Kolkata', label: 'Kolkata (IST)' }, { value: 'Asia/Bangkok', label: 'Bangkok (ICT)' }, { value: 'Asia/Singapore', label: 'Singapore (SGT)' }, { value: 'Asia/Hong_Kong', label: 'Hong Kong (HKT)' }, { value: 'Asia/Shanghai', label: 'Shanghai (CST)' }, { value: 'Asia/Tokyo', label: 'Tokyo (JST)' }, { value: 'Asia/Seoul', label: 'Seoul (KST)' }, { value: 'Australia/Sydney', label: 'Sydney (AEDT/AEST)' }, { value: 'Australia/Melbourne', label: 'Melbourne (AEDT/AEST)' }, { value: 'Australia/Brisbane', label: 'Brisbane (AEST)' }, { value: 'Pacific/Auckland', label: 'Auckland (NZDT/NZST)' }, ]; /** * Helper to validate email format */ export function isValidEmail(email: string): boolean { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } /** * Helper to validate URL format */ export function isValidUrl(url: string): boolean { try { new URL(url); return true; } catch { return false; } } /** * Helper to format timestamp for display */ export function formatTimestamp(isoString: string): string { const date = new Date(isoString); return date.toLocaleString('en-GB', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', }); }