You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

185 lines
4.9 KiB
TypeScript

/**
* 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',
});
}