{"version":3,"sources":["../../src/client/utils/date-helpers.ts","../../src/client/utils/formatting.ts","../../src/shared/utils.ts","../../src/shared/enums.ts","../../src/client/utils/validation.ts","../../src/client/utils/event-processing.ts","../../src/client/components/EventCard.tsx","../../src/client/components/CalendarView.tsx","../../src/shared/constants.ts"],"sourcesContent":["/**\n * Pure date utility functions - browser-safe\n */\n\n// Note: formatDateAustralian is now exported from shared utils\n\n// Australian time formatting\nexport const formatTimeAustralian = (date: Date | string): string => {\n  const d = typeof date === 'string' ? new Date(date) : date;\n  return d.toLocaleTimeString('en-AU', {\n    hour: '2-digit',\n    minute: '2-digit',\n    hour12: true\n  });\n};\n\n// Australian datetime formatting\nexport const formatDateTimeAustralian = (date: Date | string): string => {\n  const d = typeof date === 'string' ? new Date(date) : date;\n  return d.toLocaleString('en-AU', {\n    day: '2-digit',\n    month: '2-digit',\n    year: 'numeric',\n    hour: '2-digit',\n    minute: '2-digit',\n    hour12: true\n  });\n};\n\n// Calculate days until a date\nexport const daysUntil = (date: Date | string): number => {\n  const targetDate = typeof date === 'string' ? new Date(date) : date;\n  const now = new Date();\n  const diffTime = targetDate.getTime() - now.getTime();\n  return Math.ceil(diffTime / (1000 * 60 * 60 * 24));\n};\n\n// Check if date is today\nexport const isToday = (date: Date | string): boolean => {\n  const d = typeof date === 'string' ? new Date(date) : date;\n  const today = new Date();\n  return d.toDateString() === today.toDateString();\n};\n\n// Check if date is in the past\nexport const isPast = (date: Date | string): boolean => {\n  const d = typeof date === 'string' ? new Date(date) : date;\n  return d < new Date();\n};\n\n// Check if date is in the future\nexport const isFuture = (date: Date | string): boolean => {\n  const d = typeof date === 'string' ? new Date(date) : date;\n  return d > new Date();\n};\n\n// Check if date is this week\nexport const isThisWeek = (date: Date | string): boolean => {\n  const d = typeof date === 'string' ? new Date(date) : date;\n  const now = new Date();\n  const startOfWeek = new Date(now.setDate(now.getDate() - now.getDay()));\n  const endOfWeek = new Date(now.setDate(now.getDate() - now.getDay() + 6));\n  return d >= startOfWeek && d <= endOfWeek;\n};\n\n// Check if date is this month\nexport const isThisMonth = (date: Date | string): boolean => {\n  const d = typeof date === 'string' ? new Date(date) : date;\n  const now = new Date();\n  return d.getMonth() === now.getMonth() && d.getFullYear() === now.getFullYear();\n};\n\n// Get start of day\nexport const startOfDay = (date: Date | string): Date => {\n  const d = typeof date === 'string' ? new Date(date) : new Date(date);\n  d.setHours(0, 0, 0, 0);\n  return d;\n};\n\n// Get end of day\nexport const endOfDay = (date: Date | string): Date => {\n  const d = typeof date === 'string' ? new Date(date) : new Date(date);\n  d.setHours(23, 59, 59, 999);\n  return d;\n};\n\n// Add days to date\nexport const addDays = (date: Date | string, days: number): Date => {\n  const d = typeof date === 'string' ? new Date(date) : new Date(date);\n  d.setDate(d.getDate() + days);\n  return d;\n};\n\n// Add months to date\nexport const addMonths = (date: Date | string, months: number): Date => {\n  const d = typeof date === 'string' ? new Date(date) : new Date(date);\n  d.setMonth(d.getMonth() + months);\n  return d;\n};\n\n// Get month name\nexport const getMonthName = (date: Date | string): string => {\n  const d = typeof date === 'string' ? new Date(date) : date;\n  return d.toLocaleDateString('en-AU', { month: 'long' });\n};\n\n// Get day name\nexport const getDayName = (date: Date | string): string => {\n  const d = typeof date === 'string' ? new Date(date) : date;\n  return d.toLocaleDateString('en-AU', { weekday: 'long' });\n}; ","/**\n * Australian formatting utilities - browser-safe\n */\n\n// Currency formatting (Australian Dollar)\nexport const formatCurrencyAUD = (amount: number): string => {\n  return new Intl.NumberFormat('en-AU', {\n    style: 'currency',\n    currency: 'AUD',\n    minimumFractionDigits: 2\n  }).format(amount);\n};\n\n// Phone number formatting (Australian format)\nexport const formatPhoneAustralian = (phone: string): string => {\n  // Remove all non-digit characters\n  const cleaned = phone.replace(/\\D/g, '');\n  \n  // Handle different Australian phone number formats\n  if (cleaned.length === 10) {\n    // Mobile: 0412 345 678\n    if (cleaned.startsWith('04')) {\n      return cleaned.replace(/(\\d{4})(\\d{3})(\\d{3})/, '$1 $2 $3');\n    }\n    // Landline: (02) 1234 5678\n    else if (cleaned.startsWith('02') || cleaned.startsWith('03') || \n             cleaned.startsWith('07') || cleaned.startsWith('08')) {\n      return cleaned.replace(/(\\d{2})(\\d{4})(\\d{4})/, '($1) $2 $3');\n    }\n  }\n  \n  // Return original if doesn't match expected patterns\n  return phone;\n};\n\n// Address formatting (Australian style)\nexport const formatAddressAustralian = (address: {\n  street?: string;\n  suburb?: string;\n  state?: string;\n  postcode?: string;\n  country?: string;\n}): string => {\n  const parts = [];\n  \n  if (address.street) parts.push(address.street);\n  if (address.suburb) parts.push(address.suburb);\n  if (address.state && address.postcode) {\n    parts.push(`${address.state} ${address.postcode}`);\n  } else if (address.state) {\n    parts.push(address.state);\n  } else if (address.postcode) {\n    parts.push(address.postcode);\n  }\n  if (address.country && address.country !== 'Australia') {\n    parts.push(address.country);\n  }\n  \n  return parts.join(', ');\n};\n\n// Percentage formatting\nexport const formatPercentage = (value: number, decimals: number = 1): string => {\n  return `${value.toFixed(decimals)}%`;\n};\n\n// Number formatting with Australian locale\nexport const formatNumber = (value: number, decimals: number = 0): string => {\n  return new Intl.NumberFormat('en-AU', {\n    minimumFractionDigits: decimals,\n    maximumFractionDigits: decimals\n  }).format(value);\n};\n\n// Duration formatting (minutes to hours:minutes)\nexport const formatDuration = (minutes: number): string => {\n  const hours = Math.floor(minutes / 60);\n  const mins = minutes % 60;\n  \n  if (hours === 0) {\n    return `${mins} min`;\n  } else if (mins === 0) {\n    return hours === 1 ? `${hours} hr` : `${hours} hrs`;\n  } else {\n    const hourText = hours === 1 ? 'hr' : 'hrs';\n    return `${hours} ${hourText} ${mins} min`;\n  }\n};\n\n// File size formatting\nexport const formatFileSize = (bytes: number): string => {\n  const sizes = ['Bytes', 'KB', 'MB', 'GB'];\n  if (bytes === 0) return '0 Bytes';\n  \n  const i = Math.floor(Math.log(bytes) / Math.log(1024));\n  return `${Math.round(bytes / Math.pow(1024, i) * 100) / 100} ${sizes[i]}`;\n};\n\n// Capitalize first letter of each word\nexport const capitalizeWords = (text: string): string => {\n  return text.replace(/\\w\\S*/g, (txt) => \n    txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()\n  );\n};\n\n// Truncate text with ellipsis\nexport const truncateText = (text: string, maxLength: number): string => {\n  if (text.length <= maxLength) return text;\n  return text.substr(0, maxLength - 3) + '...';\n};\n\n// Format initials from name\nexport const getInitials = (name: string): string => {\n  return name\n    .split(' ')\n    .map(word => word.charAt(0).toUpperCase())\n    .join('')\n    .substr(0, 2);\n}; ","/**\n * @file Shared utility functions for the calendar library.\n * These utilities are safe to use in both client and server environments.\n */\n\n/**\n * Formats a date in Australian format (dd/mmm/yyyy).\n * Uses UTC date to avoid timezone issues in tests.\n */\nexport function formatDateAustralian(date: Date): string {\n  const months = [\n    'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'\n  ];\n  \n  const day = date.getUTCDate().toString().padStart(2, '0');\n  const month = months[date.getUTCMonth()];\n  const year = date.getUTCFullYear();\n  \n  return `${day}/${month}/${year}`;\n}\n\n/**\n * Calculates the duration between two dates in minutes.\n */\nexport function getDurationMinutes(start: Date, end: Date): number {\n  return Math.round((end.getTime() - start.getTime()) / (1000 * 60));\n}\n\n/**\n * Checks if two dates are on the same day.\n */\nexport function isSameDay(date1: Date, date2: Date): boolean {\n  return date1.toDateString() === date2.toDateString();\n}\n\n/**\n * Gets the start of week (Monday) for a given date.\n */\nexport function getStartOfWeek(date: Date): Date {\n  const result = new Date(date);\n  const day = result.getDay();\n  const diff = result.getDate() - day + (day === 0 ? -6 : 1); // Adjust when day is Sunday\n  result.setDate(diff);\n  result.setHours(0, 0, 0, 0);\n  return result;\n}\n\n/**\n * Gets the end of week (Sunday) for a given date.\n */\nexport function getEndOfWeek(date: Date): Date {\n  const result = new Date(date);\n  const day = result.getDay();\n  const diff = result.getDate() - day + (day === 0 ? 0 : 7); // Adjust when day is Sunday\n  result.setDate(diff);\n  result.setHours(23, 59, 59, 999);\n  return result;\n}\n\n/**\n * Validates an email address.\n */\nexport function isValidEmail(email: string): boolean {\n  const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n  return emailRegex.test(email);\n}\n\n/**\n * Validates a phone number (basic validation).\n */\nexport function isValidPhone(phone: string): boolean {\n  // Basic validation for Australian phone numbers\n  const phoneRegex = /^(\\+61|0)[2-9]\\d{8}$/;\n  return phoneRegex.test(phone.replace(/\\s/g, ''));\n}\n\n/**\n * Generates a unique ID (simple implementation for client-side).\n * Note: For production, use a proper UUID library on the server.\n */\nexport function generateTempId(): string {\n  return `temp_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;\n} ","/**\n * @file Shared enums for the calendar library.\n * These enums are safe to use in both client and server environments.\n */\n\n/**\n * Event types for musician-specific functionality.\n */\nexport const EVENT_TYPES = {\n  GIG: 'gig',\n  LESSON: 'lesson',\n  AUDITION: 'audition',\n  PRACTICE: 'practice',\n  REHEARSAL: 'rehearsal',\n  RECORDING: 'recording',\n  MEETING: 'meeting'\n} as const;\n\nexport type EventType = typeof EVENT_TYPES[keyof typeof EVENT_TYPES];\n\n/**\n * Payment status options.\n */\nexport const PAYMENT_STATUS = {\n  PENDING: 'Pending',\n  PAID: 'Paid',\n  OVERDUE: 'Overdue',\n  CANCELLED: 'Cancelled'\n} as const;\n\nexport type PaymentStatus = typeof PAYMENT_STATUS[keyof typeof PAYMENT_STATUS];\n\n/**\n * Event status options.\n */\nexport const EVENT_STATUS = {\n  CONFIRMED: 'Confirmed',\n  TENTATIVE: 'Tentative',\n  CANCELLED: 'Cancelled',\n  COMPLETED: 'Completed'\n} as const;\n\nexport type EventStatus = typeof EVENT_STATUS[keyof typeof EVENT_STATUS];\n\n/**\n * Calendar types.\n */\nexport const CALENDAR_TYPES = {\n  INDIVIDUAL: 'individual',\n  GROUP: 'group',\n  SHARED: 'shared'\n} as const;\n\nexport type CalendarType = typeof CALENDAR_TYPES[keyof typeof CALENDAR_TYPES];\n\n/**\n * Student levels for lessons.\n */\nexport const STUDENT_LEVELS = {\n  BEGINNER: 'Beginner',\n  INTERMEDIATE: 'Intermediate',\n  ADVANCED: 'Advanced',\n  PROFESSIONAL: 'Professional'\n} as const;\n\nexport type StudentLevel = typeof STUDENT_LEVELS[keyof typeof STUDENT_LEVELS];\n\n/**\n * Difficulty levels for pieces/repertoire.\n */\nexport const DIFFICULTY_LEVELS = {\n  EASY: 'Easy',\n  MEDIUM: 'Medium',\n  HARD: 'Hard',\n  EXPERT: 'Expert'\n} as const;\n\nexport type DifficultyLevel = typeof DIFFICULTY_LEVELS[keyof typeof DIFFICULTY_LEVELS];\n\n/**\n * Common musical genres.\n */\nexport const GENRES = {\n  CLASSICAL: 'Classical',\n  JAZZ: 'Jazz',\n  ROCK: 'Rock',\n  POP: 'Pop',\n  BLUES: 'Blues',\n  COUNTRY: 'Country',\n  FOLK: 'Folk',\n  ELECTRONIC: 'Electronic',\n  WORLD: 'World Music',\n  OTHER: 'Other'\n} as const;\n\nexport type Genre = typeof GENRES[keyof typeof GENRES];\n\n/**\n * Common instruments.\n */\nexport const INSTRUMENTS = {\n  PIANO: 'Piano',\n  GUITAR: 'Guitar',\n  VIOLIN: 'Violin',\n  DRUMS: 'Drums',\n  BASS: 'Bass',\n  SAXOPHONE: 'Saxophone',\n  TRUMPET: 'Trumpet',\n  FLUTE: 'Flute',\n  CELLO: 'Cello',\n  VOICE: 'Voice',\n  OTHER: 'Other'\n} as const;\n\nexport type Instrument = typeof INSTRUMENTS[keyof typeof INSTRUMENTS]; ","/**\n * @file Client-side validation for the calendar library.\n * These validation functions are safe for browser environments.\n */\n\nimport { isValidEmail, isValidPhone } from '../../shared/utils';\nimport type { EventFormData, CreateEventData } from '../types/events';\nimport type { CalendarFormData } from '../types/calendar';\nimport { EVENT_TYPES, PAYMENT_STATUS, EVENT_STATUS } from '../../shared/enums';\n\nexport interface ValidationResult {\n  isValid: boolean;\n  errors: Record<string, string[]>;\n}\n\n// Income/Expense form data types for validation\nexport interface IncomeFormData {\n  description: string;\n  amount: number;\n  currency: string;\n  notes?: string;\n}\n\nexport interface ExpenseFormData {\n  description: string;\n  amount: number;\n  currency: string;\n  notes?: string;\n  receipt?: string;\n}\n\n/**\n * Validates event form data.\n */\nexport function validateEvent(data: Partial<EventFormData>): ValidationResult {\n  const errors: Record<string, string[]> = {};\n\n  // Required fields\n  if (!data.title || data.title.trim().length === 0) {\n    errors.title = ['Event title is required'];\n  } else if (data.title.length > 200) {\n    errors.title = ['Event title must not exceed 200 characters'];\n  }\n\n  if (!data.startDate) {\n    errors.startDate = ['Start date is required'];\n  }\n\n  if (!data.startTime) {\n    errors.startTime = ['Start time is required'];\n  }\n\n  if (data.startDate && data.endDate && data.startTime && data.endTime) {\n    const start = new Date(`${data.startDate}T${data.startTime}`);\n    const end = new Date(`${data.endDate || data.startDate}T${data.endTime || data.startTime}`);\n    \n    if (start >= end) {\n      errors.endTime = ['End time must be after start time'];\n    }\n    \n    // Check for reasonable duration (not more than 24 hours for most events)\n    const durationHours = (end.getTime() - start.getTime()) / (1000 * 60 * 60);\n    if (durationHours > 24) {\n      errors.endTime = ['Event duration cannot exceed 24 hours'];\n    }\n  }\n\n  if (!data.eventType) {\n    errors.eventType = ['Event type is required'];\n  } else if (!Object.values(EVENT_TYPES).includes(data.eventType as any)) {\n    errors.eventType = ['Invalid event type'];\n  }\n\n  if (!data.calendarId) {\n    errors.calendarId = ['Calendar selection is required'];\n  }\n\n  // Optional field validations\n  if (data.description && data.description.length > 1000) {\n    errors.description = ['Description must not exceed 1000 characters'];\n  }\n\n  if (data.status && !Object.values(EVENT_STATUS).includes(data.status as any)) {\n    errors.status = ['Invalid event status'];\n  }\n\n  if (data.notes && data.notes.length > 1000) {\n    errors.notes = ['Notes must not exceed 1000 characters'];\n  }\n\n  // Recurrence validations\n  if (data.isRecurring && !data.recurrenceRule) {\n    errors.recurrenceRule = ['Recurrence rule is required for recurring events'];\n  }\n\n  if (data.recurrenceRule && !data.isRecurring) {\n    errors.isRecurring = ['Recurring flag must be set when recurrence rule is provided'];\n  }\n\n  if (data.recurrenceEndDate && data.startDate) {\n    const recurrenceEnd = new Date(data.recurrenceEndDate);\n    const eventStart = new Date(data.startDate);\n    if (recurrenceEnd <= eventStart) {\n      errors.recurrenceEndDate = ['Recurrence end date must be after event start date'];\n    }\n  }\n\n  if (data.maxOccurrences !== undefined && data.maxOccurrences < 1) {\n    errors.maxOccurrences = ['Maximum occurrences must be at least 1'];\n  }\n\n  return {\n    isValid: Object.keys(errors).length === 0,\n    errors\n  };\n}\n\n/**\n * Validates income form data.\n */\nexport function validateIncome(data: Partial<IncomeFormData>): ValidationResult {\n  const errors: Record<string, string[]> = {};\n\n  if (!data.description || data.description.trim().length === 0) {\n    errors.description = ['Income description is required'];\n  } else if (data.description.length > 200) {\n    errors.description = ['Description must not exceed 200 characters'];\n  }\n\n  if (data.amount === undefined || data.amount === null) {\n    errors.amount = ['Amount is required'];\n  } else if (data.amount < 0) {\n    errors.amount = ['Amount must be positive'];\n  } else if (data.amount > 999999.99) {\n    errors.amount = ['Amount must not exceed $999,999.99'];\n  }\n\n  if (!data.currency || data.currency.trim().length === 0) {\n    errors.currency = ['Currency is required'];\n  } else if (!/^[A-Z]{3}$/.test(data.currency)) {\n    errors.currency = ['Currency must be a valid 3-letter code (e.g., AUD, USD)'];\n  }\n\n  if (data.notes && data.notes.length > 500) {\n    errors.notes = ['Notes must not exceed 500 characters'];\n  }\n\n  return {\n    isValid: Object.keys(errors).length === 0,\n    errors\n  };\n}\n\n/**\n * Validates expense form data.\n */\nexport function validateExpense(data: Partial<ExpenseFormData>): ValidationResult {\n  const errors: Record<string, string[]> = {};\n\n  if (!data.description || data.description.trim().length === 0) {\n    errors.description = ['Expense description is required'];\n  } else if (data.description.length > 200) {\n    errors.description = ['Description must not exceed 200 characters'];\n  }\n\n  if (data.amount === undefined || data.amount === null) {\n    errors.amount = ['Amount is required'];\n  } else if (data.amount < 0) {\n    errors.amount = ['Amount must be positive'];\n  } else if (data.amount > 999999.99) {\n    errors.amount = ['Amount must not exceed $999,999.99'];\n  }\n\n  if (!data.currency || data.currency.trim().length === 0) {\n    errors.currency = ['Currency is required'];\n  } else if (!/^[A-Z]{3}$/.test(data.currency)) {\n    errors.currency = ['Currency must be a valid 3-letter code (e.g., AUD, USD)'];\n  }\n\n  if (data.notes && data.notes.length > 500) {\n    errors.notes = ['Notes must not exceed 500 characters'];\n  }\n\n  // Receipt validation (if provided)\n  if (data.receipt && data.receipt.length > 500) {\n    errors.receipt = ['Receipt path must not exceed 500 characters'];\n  }\n\n  return {\n    isValid: Object.keys(errors).length === 0,\n    errors\n  };\n}\n\n/**\n * Validates calendar form data.\n */\nexport function validateCalendar(data: Partial<CalendarFormData>): ValidationResult {\n  const errors: Record<string, string[]> = {};\n\n  if (!data.name || data.name.trim().length === 0) {\n    errors.name = ['Calendar name is required'];\n  } else if (data.name.length > 100) {\n    errors.name = ['Calendar name must not exceed 100 characters'];\n  }\n\n  if (data.description && data.description.length > 500) {\n    errors.description = ['Description must not exceed 500 characters'];\n  }\n\n  if (data.color && !/^#[0-9A-F]{6}$/i.test(data.color)) {\n    errors.color = ['Color must be a valid hex color code'];\n  }\n\n  if (data.timeZone && data.timeZone.length > 50) {\n    errors.timeZone = ['Time zone must not exceed 50 characters'];\n  }\n\n  return {\n    isValid: Object.keys(errors).length === 0,\n    errors\n  };\n}\n\n/**\n * Validates venue form data.\n */\nexport function validateVenue(data: {\n  name?: string;\n  address?: string;\n  city?: string;\n  state?: string;\n  country?: string;\n  website?: string;\n  contactEmail?: string;\n  contactPhone?: string;\n  notes?: string;\n}): ValidationResult {\n  const errors: Record<string, string[]> = {};\n\n  if (!data.name || data.name.trim().length === 0) {\n    errors.name = ['Venue name is required'];\n  } else if (data.name.length > 200) {\n    errors.name = ['Venue name must not exceed 200 characters'];\n  }\n\n  if (data.address && data.address.length > 300) {\n    errors.address = ['Address must not exceed 300 characters'];\n  }\n\n  if (data.city && data.city.length > 100) {\n    errors.city = ['City must not exceed 100 characters'];\n  }\n\n  if (data.state && data.state.length > 100) {\n    errors.state = ['State must not exceed 100 characters'];\n  }\n\n  if (data.country && data.country.length > 100) {\n    errors.country = ['Country must not exceed 100 characters'];\n  }\n\n  if (data.website && !isValidWebsite(data.website)) {\n    errors.website = ['Please enter a valid website URL'];\n  }\n\n  if (data.contactEmail && !isValidEmail(data.contactEmail)) {\n    errors.contactEmail = ['Please enter a valid email address'];\n  }\n\n  if (data.contactPhone && !isValidPhone(data.contactPhone)) {\n    errors.contactPhone = ['Please enter a valid phone number'];\n  }\n\n  if (data.notes && data.notes.length > 1000) {\n    errors.notes = ['Notes must not exceed 1000 characters'];\n  }\n\n  return {\n    isValid: Object.keys(errors).length === 0,\n    errors\n  };\n}\n\n/**\n * Validates contact form data.\n */\nexport function validateContact(data: {\n  name?: string;\n  email?: string;\n  phone?: string;\n  role?: string;\n  notes?: string;\n}): ValidationResult {\n  const errors: Record<string, string[]> = {};\n\n  if (!data.name || data.name.trim().length === 0) {\n    errors.name = ['Contact name is required'];\n  } else if (data.name.length > 200) {\n    errors.name = ['Contact name must not exceed 200 characters'];\n  }\n\n  if (data.email && !isValidEmail(data.email)) {\n    errors.email = ['Please enter a valid email address'];\n  }\n\n  if (data.phone && !isValidPhone(data.phone)) {\n    errors.phone = ['Please enter a valid phone number'];\n  }\n\n  if (data.role && data.role.length > 100) {\n    errors.role = ['Role must not exceed 100 characters'];\n  }\n\n  if (data.notes && data.notes.length > 1000) {\n    errors.notes = ['Notes must not exceed 1000 characters'];\n  }\n\n  return {\n    isValid: Object.keys(errors).length === 0,\n    errors\n  };\n}\n\n/**\n * Validates recurrence rule format.\n */\nexport function validateRecurrenceRule(rule: string): ValidationResult {\n  const errors: Record<string, string[]> = {};\n\n  if (!rule || rule.trim().length === 0) {\n    errors.rule = ['Recurrence rule is required'];\n    return { isValid: false, errors };\n  }\n\n  // Basic RRULE format validation\n  if (!rule.startsWith('RRULE:')) {\n    errors.rule = ['Recurrence rule must start with \"RRULE:\"'];\n  }\n\n  // Check for required FREQ parameter\n  if (!rule.includes('FREQ=')) {\n    errors.rule = ['Recurrence rule must include FREQ parameter'];\n  }\n\n  return {\n    isValid: Object.keys(errors).length === 0,\n    errors\n  };\n}\n\n// Helper function for website validation\nfunction isValidWebsite(url: string): boolean {\n  try {\n    const urlObj = new URL(url);\n    return urlObj.protocol === 'http:' || urlObj.protocol === 'https:';\n  } catch {\n    return false;\n  }\n} ","/**\n * @file Client-side event processing utilities.\n * These utilities are safe for browser environments and work with rrule for recurrence.\n */\n\nimport { RRule } from 'rrule';\nimport type { IEvent } from '../../shared/types';\nimport type { ClientEvent, EventFilters, EventsByDate, EventFinancialSummary } from '../types/events';\nimport { formatDateAustralian } from '../../shared/utils';\nimport { formatTimeAustralian, daysUntil, isPast, isFuture } from './date-helpers';\nimport { formatCurrencyAUD } from './formatting';\n\n/**\n * Expands a recurring event into multiple occurrences within a date range.\n */\nexport function expandRecurrence(\n  event: IEvent,\n  startRange: Date,\n  endRange: Date,\n  maxOccurrences: number = 100\n): IEvent[] {\n  if (!event.recurrenceRule) {\n    // Non-recurring event - return single occurrence if it falls within range\n    if (event.start >= startRange && event.start <= endRange) {\n      return [event];\n    }\n    return [];\n  }\n\n  try {\n    // Create RRule with the event's start date as DTSTART\n    const rule = new RRule({\n      ...RRule.parseString(event.recurrenceRule),\n      dtstart: event.start\n    });\n    \n    // Get occurrences within the date range\n    const occurrences = rule.between(startRange, endRange, true);\n    \n    // Limit the number of occurrences\n    const limitedOccurrences = occurrences.slice(0, maxOccurrences);\n    \n    // Create event instances for each occurrence\n    return limitedOccurrences.map((occurrenceStart, index) => {\n      const duration = event.end.getTime() - event.start.getTime();\n      const occurrenceEnd = new Date(occurrenceStart.getTime() + duration);\n      \n      return {\n        ...event,\n        id: `${event.id}_${index}`,\n        start: occurrenceStart,\n        end: occurrenceEnd\n      };\n    });\n  } catch (error) {\n    console.warn('Failed to parse recurrence rule:', event.recurrenceRule, error);\n    return [event]; // Return original event if parsing fails\n  }\n}\n\n/**\n * Enhances a client event with computed properties.\n */\nexport function enhanceClientEvent(event: ClientEvent): ClientEvent {\n  const enhanced = { ...event };\n\n  // Calculate duration\n  enhanced.duration = Math.round((event.end.getTime() - event.start.getTime()) / (1000 * 60));\n\n  // Calculate financial totals\n  if (event.income) {\n    enhanced.totalIncome = event.income.reduce((sum: number, income: any) => sum + income.amount, 0);\n  }\n  \n  if (event.expenses) {\n    enhanced.totalExpenses = event.expenses.reduce((sum: number, expense: any) => sum + expense.amount, 0);\n  }\n\n  // Calculate profit\n  const totalIncome = enhanced.totalIncome || 0;\n  const totalExpenses = enhanced.totalExpenses || 0;\n  enhanced.profit = totalIncome - totalExpenses;\n  enhanced.netProfit = enhanced.profit;\n\n  // Add formatted dates and times\n  enhanced.displayDate = formatDateAustralian(event.start);\n  enhanced.formattedDate = formatDateAustralian(event.start);\n  enhanced.formattedTime = formatTimeAustralian(event.start);\n\n  // Add formatted duration\n  const hours = Math.floor(enhanced.duration / 60);\n  const minutes = enhanced.duration % 60;\n  if (hours === 0) {\n    enhanced.formattedDuration = `${minutes} min${minutes !== 1 ? 's' : ''}`;\n  } else if (minutes === 0) {\n    enhanced.formattedDuration = `${hours} hr${hours !== 1 ? 's' : ''}`;\n  } else {\n    enhanced.formattedDuration = `${hours} hr${hours !== 1 ? 's' : ''} ${minutes} min`;\n  }\n\n  // Add temporal properties\n  enhanced.isPast = isPast(event.start);\n  enhanced.isUpcoming = isFuture(event.start);\n  enhanced.daysUntil = daysUntil(event.start);\n\n  return enhanced;\n}\n\n/**\n * Filters events based on provided criteria.\n */\nexport function filterEvents(events: ClientEvent[], filters: EventFilters): ClientEvent[] {\n  return events.filter(event => {\n    // Filter by event type\n    if (filters.eventType && filters.eventType.length > 0) {\n      if (!filters.eventType.includes(event.type)) {\n        return false;\n      }\n    }\n\n    // Filter by status\n    if (filters.status && filters.status.length > 0) {\n      if (!event.status || !filters.status.includes(event.status)) {\n        return false;\n      }\n    }\n\n    // Filter by calendar ID\n    if (filters.calendarId && filters.calendarId.length > 0) {\n      if (!filters.calendarId.includes(event.calendarId)) {\n        return false;\n      }\n    }\n\n    // Filter by venue ID\n    if (filters.venueId && filters.venueId.length > 0) {\n      if (!event.venueId || !filters.venueId.includes(event.venueId)) {\n        return false;\n      }\n    }\n\n    // Filter by date range\n    if (filters.dateRange) {\n      if (event.start < filters.dateRange.start || event.start > filters.dateRange.end) {\n        return false;\n      }\n    }\n\n    // Filter by search query\n    if (filters.searchQuery) {\n      const query = filters.searchQuery.toLowerCase();\n      const searchableText = [\n        event.summary,\n        event.description,\n        event.genre,\n        event.instrument\n      ].filter(Boolean).join(' ').toLowerCase();\n      \n      if (!searchableText.includes(query)) {\n        return false;\n      }\n    }\n\n    // Filter by upcoming/past\n    if (filters.isUpcoming !== undefined) {\n      const isUpcoming = isFuture(event.start);\n      if (filters.isUpcoming !== isUpcoming) {\n        return false;\n      }\n    }\n\n    if (filters.isPast !== undefined) {\n      const isPastEvent = isPast(event.start);\n      if (filters.isPast !== isPastEvent) {\n        return false;\n      }\n    }\n\n    return true;\n  });\n}\n\n/**\n * Sorts events based on criteria.\n */\nexport type EventSortOptions = {\n  field: 'start' | 'end' | 'summary' | 'type' | 'createdAt';\n  direction: 'asc' | 'desc';\n};\n\nexport function sortEvents(events: ClientEvent[], sortOptions: EventSortOptions): ClientEvent[] {\n  return [...events].sort((a, b) => {\n    let aValue: any;\n    let bValue: any;\n\n    switch (sortOptions.field) {\n      case 'start':\n        aValue = a.start.getTime();\n        bValue = b.start.getTime();\n        break;\n      case 'end':\n        aValue = a.end.getTime();\n        bValue = b.end.getTime();\n        break;\n      case 'summary':\n        aValue = a.summary.toLowerCase();\n        bValue = b.summary.toLowerCase();\n        break;\n      case 'type':\n        aValue = a.type.toLowerCase();\n        bValue = b.type.toLowerCase();\n        break;\n      case 'createdAt':\n        aValue = a.createdAt.getTime();\n        bValue = b.createdAt.getTime();\n        break;\n      default:\n        return 0;\n    }\n\n    if (aValue < bValue) {\n      return sortOptions.direction === 'asc' ? -1 : 1;\n    }\n    if (aValue > bValue) {\n      return sortOptions.direction === 'asc' ? 1 : -1;\n    }\n    return 0;\n  });\n}\n\n/**\n * Groups events by date.\n */\nexport function groupEventsByDate(events: ClientEvent[]): EventsByDate {\n  return events.reduce((groups, event) => {\n    const dateKey = formatDateAustralian(event.start);\n    if (!groups[dateKey]) {\n      groups[dateKey] = [];\n    }\n    groups[dateKey].push(event);\n    return groups;\n  }, {} as EventsByDate);\n}\n\n/**\n * Gets upcoming events (future events).\n */\nexport function getUpcomingEvents(events: ClientEvent[]): ClientEvent[] {\n  const now = new Date();\n  return events\n    .filter(event => event.start > now)\n    .sort((a, b) => a.start.getTime() - b.start.getTime());\n}\n\n/**\n * Gets today's events.\n */\nexport function getTodaysEvents(events: ClientEvent[]): ClientEvent[] {\n  const today = new Date();\n  const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate());\n  const endOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59, 999);\n\n  return events.filter(event => event.start >= startOfDay && event.start <= endOfDay);\n}\n\n/**\n * Calculates financial summary for a set of events.\n */\nexport function calculateFinancialSummary(events: ClientEvent[]): EventFinancialSummary {\n  let totalIncome = 0;\n  let totalExpenses = 0;\n  let eventCount = 0;\n\n  events.forEach(event => {\n    if (event.income) {\n      totalIncome += event.income.reduce((sum: number, income: any) => sum + income.amount, 0);\n    }\n    if (event.expenses) {\n      totalExpenses += event.expenses.reduce((sum: number, expense: any) => sum + expense.amount, 0);\n    }\n    eventCount++;\n  });\n\n  const netProfit = totalIncome - totalExpenses;\n  const averageProfit = eventCount > 0 ? netProfit / eventCount : 0;\n\n  return {\n    totalIncome,\n    totalExpenses,\n    netProfit,\n    eventCount,\n    averageProfit\n  };\n} ","import React from 'react';\nimport type { ClientEvent } from '../types/events';\nimport { formatDateAustralian } from '../../shared/utils';\nimport { formatTimeAustralian } from '../utils/date-helpers';\nimport { formatCurrencyAUD } from '../utils/formatting';\n\nexport interface EventCardProps {\n  event: ClientEvent;\n  onClick?: (event: ClientEvent) => void;\n  onEdit?: (event: ClientEvent) => void;\n  onDelete?: (event: ClientEvent) => void;\n  showFinancials?: boolean;\n  className?: string;\n}\n\nexport const EventCard: React.FC<EventCardProps> = ({\n  event,\n  onClick,\n  onEdit,\n  onDelete,\n  showFinancials = false,\n  className = ''\n}) => {\n  const handleClick = () => {\n    onClick?.(event);\n  };\n\n  const handleEdit = (e: React.MouseEvent) => {\n    e.stopPropagation();\n    onEdit?.(event);\n  };\n\n  const handleDelete = (e: React.MouseEvent) => {\n    e.stopPropagation();\n    onDelete?.(event);\n  };\n\n  return (\n    <div\n      className={`event-card ${className}`}\n      onClick={handleClick}\n      style={{\n        border: '1px solid #e0e0e0',\n        borderRadius: '8px',\n        padding: '16px',\n        margin: '8px 0',\n        backgroundColor: '#fff',\n        cursor: onClick ? 'pointer' : 'default',\n        boxShadow: '0 2px 4px rgba(0,0,0,0.1)',\n        transition: 'box-shadow 0.2s ease'\n      }}\n      onMouseEnter={(e) => {\n        if (onClick) {\n          e.currentTarget.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';\n        }\n      }}\n      onMouseLeave={(e) => {\n        e.currentTarget.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';\n      }}\n    >\n      <div className=\"event-card-header\" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>\n        <div className=\"event-info\" style={{ flex: 1 }}>\n          <h3 style={{ margin: '0 0 8px 0', fontSize: '18px', fontWeight: '600' }}>\n            {event.summary}\n          </h3>\n          <div className=\"event-meta\" style={{ fontSize: '14px', color: '#666', marginBottom: '8px' }}>\n            <div>\n              {event.formattedDate || formatDateAustralian(event.start)} \n              {event.formattedTime && ` at ${event.formattedTime}`}\n            </div>\n            <div style={{ marginTop: '4px' }}>\n              <span className=\"event-type\" style={{ \n                backgroundColor: '#f0f0f0', \n                padding: '2px 6px', \n                borderRadius: '4px', \n                fontSize: '12px' \n              }}>\n                {event.type}\n              </span>\n              {event.status && (\n                <span className=\"event-status\" style={{ \n                  backgroundColor: getStatusColor(event.status), \n                  color: '#fff',\n                  padding: '2px 6px', \n                  borderRadius: '4px', \n                  fontSize: '12px',\n                  marginLeft: '8px'\n                }}>\n                  {event.status}\n                </span>\n              )}\n            </div>\n          </div>\n          {event.description && (\n            <p style={{ margin: '8px 0', fontSize: '14px', color: '#555' }}>\n              {event.description.length > 100 \n                ? `${event.description.substring(0, 100)}...` \n                : event.description\n              }\n            </p>\n          )}\n          {event.venueDetails && (\n            <div style={{ fontSize: '14px', color: '#666', marginTop: '8px' }}>\n              📍 {event.venueDetails.name}\n            </div>\n          )}\n        </div>\n        \n        {(onEdit || onDelete) && (\n          <div className=\"event-actions\" style={{ display: 'flex', gap: '8px' }}>\n            {onEdit && (\n              <button\n                onClick={handleEdit}\n                style={{\n                  background: 'none',\n                  border: '1px solid #ddd',\n                  borderRadius: '4px',\n                  padding: '4px 8px',\n                  cursor: 'pointer',\n                  fontSize: '12px'\n                }}\n              >\n                Edit\n              </button>\n            )}\n            {onDelete && (\n              <button\n                onClick={handleDelete}\n                style={{\n                  background: 'none',\n                  border: '1px solid #ff4444',\n                  borderRadius: '4px',\n                  padding: '4px 8px',\n                  cursor: 'pointer',\n                  fontSize: '12px',\n                  color: '#ff4444'\n                }}\n              >\n                Delete\n              </button>\n            )}\n          </div>\n        )}\n      </div>\n\n      {showFinancials && (event.totalIncome || event.totalExpenses) && (\n        <div className=\"event-financials\" style={{ \n          marginTop: '12px', \n          padding: '12px', \n          backgroundColor: '#f8f9fa', \n          borderRadius: '4px',\n          fontSize: '14px'\n        }}>\n          <div style={{ display: 'flex', justifyContent: 'space-between' }}>\n            {event.totalIncome && (\n              <span style={{ color: '#28a745' }}>\n                Income: {formatCurrencyAUD(event.totalIncome)}\n              </span>\n            )}\n            {event.totalExpenses && (\n              <span style={{ color: '#dc3545' }}>\n                Expenses: {formatCurrencyAUD(event.totalExpenses)}\n              </span>\n            )}\n          </div>\n          {event.netProfit !== undefined && (\n            <div style={{ \n              marginTop: '4px', \n              fontWeight: '600',\n              color: event.netProfit >= 0 ? '#28a745' : '#dc3545'\n            }}>\n              Net: {formatCurrencyAUD(event.netProfit)}\n            </div>\n          )}\n        </div>\n      )}\n\n      {event.isUpcoming && event.daysUntil !== undefined && (\n        <div style={{ \n          marginTop: '8px', \n          fontSize: '12px', \n          color: '#007bff',\n          fontWeight: '500'\n        }}>\n          {event.daysUntil === 0 ? 'Today' : \n           event.daysUntil === 1 ? 'Tomorrow' : \n           `In ${event.daysUntil} days`}\n        </div>\n      )}\n    </div>\n  );\n};\n\n// Helper function to get status color\nfunction getStatusColor(status: string | undefined): string {\n  if (!status) return '#6c757d';\n  \n  switch (status.toLowerCase()) {\n    case 'confirmed':\n      return '#28a745';\n    case 'pending':\n      return '#ffc107';\n    case 'cancelled':\n      return '#dc3545';\n    case 'completed':\n      return '#17a2b8';\n    default:\n      return '#6c757d';\n  }\n} ","import React, { useState } from 'react';\nimport type { ClientEvent } from '../types/events';\nimport type { ClientCalendar } from '../types/calendar';\nimport { EventCard } from './EventCard';\nimport { formatDateAustralian } from '../../shared/utils';\nimport { isToday, isThisWeek, isThisMonth } from '../utils/date-helpers';\n\nexport interface CalendarViewProps {\n  calendar: ClientCalendar;\n  events: ClientEvent[];\n  view?: 'month' | 'week' | 'day' | 'list';\n  onEventClick?: (event: ClientEvent) => void;\n  onEventEdit?: (event: ClientEvent) => void;\n  onEventDelete?: (event: ClientEvent) => void;\n  onViewChange?: (view: 'month' | 'week' | 'day' | 'list') => void;\n  showFinancials?: boolean;\n  className?: string;\n}\n\nexport const CalendarView: React.FC<CalendarViewProps> = ({\n  calendar,\n  events,\n  view = 'list',\n  onEventClick,\n  onEventEdit,\n  onEventDelete,\n  onViewChange,\n  showFinancials = false,\n  className = ''\n}) => {\n  const [currentDate, setCurrentDate] = useState(new Date());\n\n  // Filter events based on current view\n  const getFilteredEvents = () => {\n    const now = new Date();\n    \n    switch (view) {\n      case 'day':\n        return events.filter(event => isToday(event.start));\n      case 'week':\n        return events.filter(event => isThisWeek(event.start));\n      case 'month':\n        return events.filter(event => isThisMonth(event.start));\n      case 'list':\n      default:\n        return events.sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime());\n    }\n  };\n\n  const filteredEvents = getFilteredEvents();\n\n  const renderViewSelector = () => (\n    <div style={{ display: 'flex', gap: '8px', marginBottom: '16px' }}>\n      {(['day', 'week', 'month', 'list'] as const).map((viewOption) => (\n        <button\n          key={viewOption}\n          onClick={() => onViewChange?.(viewOption)}\n          style={{\n            padding: '8px 16px',\n            border: '1px solid #ddd',\n            borderRadius: '4px',\n            backgroundColor: view === viewOption ? '#007bff' : '#fff',\n            color: view === viewOption ? '#fff' : '#333',\n            cursor: 'pointer',\n            textTransform: 'capitalize'\n          }}\n        >\n          {viewOption}\n        </button>\n      ))}\n    </div>\n  );\n\n  const renderCalendarHeader = () => (\n    <div style={{ \n      marginBottom: '20px', \n      padding: '16px', \n      backgroundColor: '#f8f9fa', \n      borderRadius: '8px' \n    }}>\n      <h2 style={{ margin: '0 0 8px 0', fontSize: '24px', fontWeight: '600' }}>\n        {calendar.name}\n      </h2>\n      {calendar.description && (\n        <p style={{ margin: '0 0 12px 0', color: '#666' }}>\n          {calendar.description}\n        </p>\n      )}\n      <div style={{ display: 'flex', gap: '20px', fontSize: '14px', color: '#555' }}>\n        <span>📅 {filteredEvents.length} events</span>\n        {calendar.upcomingEventCount !== undefined && (\n          <span>⏰ {calendar.upcomingEventCount} upcoming</span>\n        )}\n        {showFinancials && calendar.netProfit !== undefined && (\n          <span style={{ \n            color: calendar.netProfit >= 0 ? '#28a745' : '#dc3545',\n            fontWeight: '600'\n          }}>\n            💰 Net: ${calendar.netProfit.toFixed(2)}\n          </span>\n        )}\n      </div>\n    </div>\n  );\n\n  const renderListView = () => (\n    <div className=\"calendar-list-view\">\n      {filteredEvents.length === 0 ? (\n        <div style={{ \n          textAlign: 'center', \n          padding: '40px', \n          color: '#666',\n          backgroundColor: '#f8f9fa',\n          borderRadius: '8px'\n        }}>\n          <p>No events found for this view.</p>\n        </div>\n      ) : (\n        <div>\n          {filteredEvents.map((event) => (\n            <EventCard\n              key={event.id}\n              event={event}\n              onClick={onEventClick}\n              onEdit={onEventEdit}\n              onDelete={onEventDelete}\n              showFinancials={showFinancials}\n            />\n          ))}\n        </div>\n      )}\n    </div>\n  );\n\n  const renderGridView = () => {\n    // Simple grid layout for month/week/day views\n    // This is a basic implementation - you might want to use a proper calendar library\n    const groupedEvents = filteredEvents.reduce((groups, event) => {\n      const dateKey = formatDateAustralian(event.start);\n      if (!groups[dateKey]) {\n        groups[dateKey] = [];\n      }\n      groups[dateKey].push(event);\n      return groups;\n    }, {} as Record<string, ClientEvent[]>);\n\n    return (\n      <div className=\"calendar-grid-view\">\n        {Object.keys(groupedEvents).length === 0 ? (\n          <div style={{ \n            textAlign: 'center', \n            padding: '40px', \n            color: '#666',\n            backgroundColor: '#f8f9fa',\n            borderRadius: '8px'\n          }}>\n            <p>No events found for this {view}.</p>\n          </div>\n        ) : (\n          <div style={{ display: 'grid', gap: '16px' }}>\n            {Object.entries(groupedEvents).map(([date, dayEvents]) => (\n              <div key={date} style={{ \n                border: '1px solid #e0e0e0', \n                borderRadius: '8px', \n                padding: '16px',\n                backgroundColor: '#fff'\n              }}>\n                <h3 style={{ \n                  margin: '0 0 12px 0', \n                  fontSize: '16px', \n                  fontWeight: '600',\n                  color: '#333',\n                  borderBottom: '1px solid #eee',\n                  paddingBottom: '8px'\n                }}>\n                  {date}\n                </h3>\n                <div style={{ display: 'grid', gap: '8px' }}>\n                  {dayEvents.map((event) => (\n                    <div\n                      key={event.id}\n                      onClick={() => onEventClick?.(event)}\n                      style={{\n                        padding: '8px 12px',\n                        backgroundColor: '#f8f9fa',\n                        borderRadius: '4px',\n                        cursor: onEventClick ? 'pointer' : 'default',\n                        fontSize: '14px',\n                        border: '1px solid transparent'\n                      }}\n                      onMouseEnter={(e) => {\n                        if (onEventClick) {\n                          e.currentTarget.style.backgroundColor = '#e9ecef';\n                          e.currentTarget.style.borderColor = '#dee2e6';\n                        }\n                      }}\n                      onMouseLeave={(e) => {\n                        e.currentTarget.style.backgroundColor = '#f8f9fa';\n                        e.currentTarget.style.borderColor = 'transparent';\n                      }}\n                    >\n                      <div style={{ fontWeight: '500' }}>{event.summary}</div>\n                      {event.formattedTime && (\n                        <div style={{ fontSize: '12px', color: '#666' }}>\n                          {event.formattedTime}\n                        </div>\n                      )}\n                    </div>\n                  ))}\n                </div>\n              </div>\n            ))}\n          </div>\n        )}\n      </div>\n    );\n  };\n\n  return (\n    <div className={`calendar-view ${className}`}>\n      {renderCalendarHeader()}\n      {onViewChange && renderViewSelector()}\n      \n      <div className=\"calendar-content\">\n        {view === 'list' ? renderListView() : renderGridView()}\n      </div>\n    </div>\n  );\n}; ","/**\n * @file Shared constants for the calendar library.\n * These constants are safe to use in both client and server environments.\n */\n\n/**\n * Default currency for financial calculations.\n */\nexport const DEFAULT_CURRENCY = 'AUD';\n\n/**\n * Maximum event duration in hours.\n */\nexport const MAX_EVENT_DURATION_HOURS = 24;\n\n/**\n * Maximum number of recurrence occurrences.\n */\nexport const MAX_RECURRENCE_OCCURRENCES = 365;\n\n/**\n * Default event duration in minutes.\n */\nexport const DEFAULT_EVENT_DURATION_MINUTES = 60;\n\n/**\n * Maximum field lengths for validation.\n */\nexport const MAX_LENGTHS = {\n  EVENT_TITLE: 200,\n  EVENT_DESCRIPTION: 1000,\n  CALENDAR_NAME: 100,\n  CALENDAR_DESCRIPTION: 500,\n  VENUE_NAME: 200,\n  VENUE_ADDRESS: 300,\n  VENUE_CITY: 100,\n  CONTACT_NAME: 200,\n  CONTACT_ROLE: 100,\n  NOTES: 1000,\n  INCOME_DESCRIPTION: 200,\n  EXPENSE_DESCRIPTION: 200,\n  RECEIPT_PATH: 500\n} as const;\n\n/**\n * Date format patterns for different locales.\n */\nexport const DATE_FORMATS = {\n  AUSTRALIAN: 'DD/MM/YYYY',\n  AMERICAN: 'MM/DD/YYYY',\n  ISO: 'YYYY-MM-DD'\n} as const;\n\n/**\n * Time format patterns.\n */\nexport const TIME_FORMATS = {\n  TWELVE_HOUR: '12h',\n  TWENTY_FOUR_HOUR: '24h'\n} as const;\n\n/**\n * Default calendar view options.\n */\nexport const CALENDAR_VIEWS = {\n  DAY: 'day',\n  WEEK: 'week',\n  MONTH: 'month',\n  LIST: 'list'\n} as const;\n\n/**\n * Default start of week (0 = Sunday, 1 = Monday, etc.)\n */\nexport const DEFAULT_START_OF_WEEK = 1; // Monday\n\n/**\n * Australian states and territories.\n */\nexport const AUSTRALIAN_STATES = {\n  NSW: 'New South Wales',\n  VIC: 'Victoria',\n  QLD: 'Queensland',\n  WA: 'Western Australia',\n  SA: 'South Australia',\n  TAS: 'Tasmania',\n  ACT: 'Australian Capital Territory',\n  NT: 'Northern Territory'\n} as const;\n\n/**\n * Common currency codes.\n */\nexport const CURRENCIES = {\n  AUD: 'Australian Dollar',\n  USD: 'US Dollar',\n  EUR: 'Euro',\n  GBP: 'British Pound',\n  CAD: 'Canadian Dollar',\n  NZD: 'New Zealand Dollar'\n} as const;\n\n/**\n * Validation patterns.\n */\nexport const VALIDATION_PATTERNS = {\n  EMAIL: /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/,\n  PHONE_AU: /^(\\+61|0)[2-478](?:[ -]?[0-9]){8}$/,\n  CURRENCY_CODE: /^[A-Z]{3}$/,\n  HEX_COLOR: /^#[0-9A-F]{6}$/i,\n  URL: /^https?:\\/\\/.+/\n} as const;\n\n/**\n * API configuration constants.\n */\nexport const API_CONFIG = {\n  DEFAULT_PAGE_SIZE: 20,\n  MAX_PAGE_SIZE: 100,\n  REQUEST_TIMEOUT: 30000, // 30 seconds\n  RETRY_ATTEMPTS: 3\n} as const;\n\n/**\n * File upload constraints.\n */\nexport const FILE_UPLOAD = {\n  MAX_SIZE_MB: 10,\n  ALLOWED_TYPES: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf'],\n  ALLOWED_EXTENSIONS: ['.jpg', '.jpeg', '.png', '.gif', '.pdf']\n} as const; "],"mappings":"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","names":["formatTimeAustralian","date","d","Date","toLocaleTimeString","hour","minute","hour12","formatDateTimeAustralian","toLocaleString","day","month","year","daysUntil","targetDate","now","diffTime","getTime","Math","ceil","isToday","today","toDateString","isPast","isFuture","isThisWeek","startOfWeek","setDate","getDate","getDay","endOfWeek","isThisMonth","getMonth","getFullYear","startOfDay","setHours","endOfDay","addDays","days","addMonths","months","setMonth","getMonthName","toLocaleDateString","getDayName","weekday","formatCurrencyAUD","amount","Intl","NumberFormat","style","currency","minimumFractionDigits","format","formatPhoneAustralian","phone","cleaned","replace","length","startsWith","formatAddressAustralian","address","parts","street","push","suburb","state","postcode","country","join","formatPercentage","value","decimals","toFixed","formatNumber","maximumFractionDigits","formatDuration","minutes","hours","Math","floor","mins","hourText","formatFileSize","bytes","sizes","i","log","round","pow","capitalizeWords","text","txt","charAt","toUpperCase","substr","toLowerCase","truncateText","maxLength","getInitials","name","split","map","word","formatDateAustralian","date","months","day","getUTCDate","toString","padStart","month","getUTCMonth","year","getUTCFullYear","getDurationMinutes","start","end","Math","round","getTime","isSameDay","date1","date2","toDateString","getStartOfWeek","result","Date","getDay","diff","getDate","setDate","setHours","getEndOfWeek","isValidEmail","email","emailRegex","test","isValidPhone","phone","phoneRegex","replace","generateTempId","now","random","substr","EVENT_TYPES","GIG","LESSON","AUDITION","PRACTICE","REHEARSAL","RECORDING","MEETING","PAYMENT_STATUS","PENDING","PAID","OVERDUE","CANCELLED","EVENT_STATUS","CONFIRMED","TENTATIVE","COMPLETED","CALENDAR_TYPES","INDIVIDUAL","GROUP","SHARED","STUDENT_LEVELS","BEGINNER","INTERMEDIATE","ADVANCED","PROFESSIONAL","DIFFICULTY_LEVELS","EASY","MEDIUM","HARD","EXPERT","GENRES","CLASSICAL","JAZZ","ROCK","POP","BLUES","COUNTRY","FOLK","ELECTRONIC","WORLD","OTHER","INSTRUMENTS","PIANO","GUITAR","VIOLIN","DRUMS","BASS","SAXOPHONE","TRUMPET","FLUTE","CELLO","VOICE","validateEvent","data","errors","title","trim","length","startDate","startTime","endDate","endTime","start","Date","end","durationHours","getTime","eventType","Object","values","EVENT_TYPES","includes","calendarId","description","status","EVENT_STATUS","notes","isRecurring","recurrenceRule","recurrenceEndDate","recurrenceEnd","eventStart","maxOccurrences","undefined","isValid","keys","validateIncome","amount","currency","test","validateExpense","receipt","validateCalendar","name","color","timeZone","validateVenue","address","city","state","country","website","isValidWebsite","contactEmail","isValidEmail","contactPhone","isValidPhone","validateContact","email","phone","role","validateRecurrenceRule","rule","startsWith","url","urlObj","URL","protocol","RRule","expandRecurrence","event","startRange","endRange","maxOccurrences","recurrenceRule","start","rule","RRule","parseString","dtstart","occurrences","between","limitedOccurrences","slice","map","occurrenceStart","index","duration","end","getTime","occurrenceEnd","Date","id","error","console","warn","enhanceClientEvent","enhanced","Math","round","income","totalIncome","reduce","sum","amount","expenses","totalExpenses","expense","profit","netProfit","displayDate","formatDateAustralian","formattedDate","formattedTime","formatTimeAustralian","hours","floor","minutes","formattedDuration","isPast","isUpcoming","isFuture","daysUntil","filterEvents","events","filters","filter","eventType","length","includes","type","status","calendarId","venueId","dateRange","searchQuery","query","toLowerCase","searchableText","summary","description","genre","instrument","Boolean","join","undefined","isPastEvent","sortEvents","sortOptions","sort","a","b","aValue","bValue","field","createdAt","direction","groupEventsByDate","groups","dateKey","push","getUpcomingEvents","now","getTodaysEvents","today","startOfDay","getFullYear","getMonth","getDate","endOfDay","calculateFinancialSummary","eventCount","forEach","averageProfit","React","EventCard","event","onClick","onEdit","onDelete","showFinancials","className","handleClick","handleEdit","e","stopPropagation","handleDelete","div","style","border","borderRadius","padding","margin","backgroundColor","cursor","boxShadow","transition","onMouseEnter","currentTarget","onMouseLeave","display","justifyContent","alignItems","flex","h3","fontSize","fontWeight","summary","color","marginBottom","formattedDate","formatDateAustralian","start","formattedTime","marginTop","span","type","status","getStatusColor","marginLeft","description","p","length","substring","venueDetails","name","gap","button","background","totalIncome","totalExpenses","formatCurrencyAUD","netProfit","undefined","isUpcoming","daysUntil","toLowerCase","React","useState","CalendarView","calendar","events","view","onEventClick","onEventEdit","onEventDelete","onViewChange","showFinancials","className","currentDate","setCurrentDate","useState","Date","getFilteredEvents","now","filter","event","isToday","start","isThisWeek","isThisMonth","sort","a","b","getTime","filteredEvents","renderViewSelector","React","div","style","display","gap","marginBottom","map","viewOption","button","key","onClick","padding","border","borderRadius","backgroundColor","color","cursor","textTransform","renderCalendarHeader","h2","margin","fontSize","fontWeight","name","description","p","span","length","upcomingEventCount","undefined","netProfit","toFixed","renderListView","textAlign","EventCard","id","onEdit","onDelete","renderGridView","groupedEvents","reduce","groups","dateKey","formatDateAustralian","push","Object","keys","entries","date","dayEvents","h3","borderBottom","paddingBottom","onMouseEnter","e","currentTarget","borderColor","onMouseLeave","summary","formattedTime","DEFAULT_CURRENCY","MAX_EVENT_DURATION_HOURS","MAX_RECURRENCE_OCCURRENCES","DEFAULT_EVENT_DURATION_MINUTES","MAX_LENGTHS","EVENT_TITLE","EVENT_DESCRIPTION","CALENDAR_NAME","CALENDAR_DESCRIPTION","VENUE_NAME","VENUE_ADDRESS","VENUE_CITY","CONTACT_NAME","CONTACT_ROLE","NOTES","INCOME_DESCRIPTION","EXPENSE_DESCRIPTION","RECEIPT_PATH","DATE_FORMATS","AUSTRALIAN","AMERICAN","ISO","TIME_FORMATS","TWELVE_HOUR","TWENTY_FOUR_HOUR","CALENDAR_VIEWS","DAY","WEEK","MONTH","LIST","DEFAULT_START_OF_WEEK","AUSTRALIAN_STATES","NSW","VIC","QLD","WA","SA","TAS","ACT","NT","CURRENCIES","AUD","USD","EUR","GBP","CAD","NZD","VALIDATION_PATTERNS","EMAIL","PHONE_AU","CURRENCY_CODE","HEX_COLOR","URL","API_CONFIG","DEFAULT_PAGE_SIZE","MAX_PAGE_SIZE","REQUEST_TIMEOUT","RETRY_ATTEMPTS","FILE_UPLOAD","MAX_SIZE_MB","ALLOWED_TYPES","ALLOWED_EXTENSIONS"]}