// Domain models based on the Game Plan // FIX: Added PageComponent types and updated Business interface for website editor feature. export type PageComponentType = 'HEADING' | 'TEXT' | 'IMAGE' | 'BUTTON' | 'SERVICE' | 'COLUMNS'; export interface PageComponent { id: string; type: PageComponentType; content?: { text?: string; level?: 1 | 2 | 3; src?: string; alt?: string; buttonText?: string; href?: string; serviceId?: string; }; children?: PageComponent[][]; } export interface CustomDomain { id: number; domain: string; is_verified: boolean; ssl_provisioned: boolean; is_primary: boolean; verification_token: string; dns_txt_record: string; dns_txt_record_name: string; created_at: string; verified_at?: string; } export interface PlanPermissions { sms_reminders: boolean; webhooks: boolean; api_access: boolean; custom_domain: boolean; white_label: boolean; custom_oauth: boolean; plugins: boolean; tasks: boolean; export_data: boolean; video_conferencing: boolean; two_factor_auth: boolean; masked_calling: boolean; pos_system: boolean; mobile_app: boolean; } export interface Business { id: string; name: string; subdomain: string; primaryColor: string; secondaryColor: string; logoUrl?: string; emailLogoUrl?: string; logoDisplayMode?: 'logo-only' | 'text-only' | 'logo-and-text'; // How to display branding timezone?: string; // IANA timezone (e.g., 'America/New_York') timezoneDisplayMode?: 'business' | 'viewer'; // How times are displayed to users whitelabelEnabled: boolean; plan?: 'Free' | 'Professional' | 'Business' | 'Enterprise'; status?: 'Active' | 'Suspended' | 'Trial'; joinedAt?: Date; resourcesCanReschedule?: boolean; paymentsEnabled: boolean; requirePaymentMethodToBook: boolean; cancellationWindowHours: number; lateCancellationFeePercent: number; initialSetupComplete?: boolean; customDomain?: string; customDomainVerified?: boolean; bookingReturnUrl?: string; // URL to redirect customers after booking completion stripeConnectAccountId?: string; websitePages?: Record; customerDashboardContent?: PageComponent[]; trialStart?: string; trialEnd?: string; isTrialActive?: boolean; isTrialExpired?: boolean; daysLeftInTrial?: number; resourceTypes?: ResourceTypeDefinition[]; // Custom resource types // Platform-controlled permissions canManageOAuthCredentials?: boolean; // Plan permissions (what features are available based on subscription) planPermissions?: PlanPermissions; } export type UserRole = 'superuser' | 'platform_manager' | 'platform_support' | 'owner' | 'manager' | 'staff' | 'resource' | 'customer'; export interface NotificationPreferences { email: boolean; sms: boolean; in_app: boolean; appointment_reminders: boolean; marketing: boolean; } export interface QuotaOverage { id: number; quota_type: string; display_name: string; current_usage: number; allowed_limit: number; overage_amount: number; days_remaining: number; grace_period_ends_at: string; } export interface User { id: string | number; username?: string; name: string; email: string; role: UserRole; avatarUrl?: string; phone?: string; email_verified?: boolean; two_factor_enabled?: boolean; timezone?: string; locale?: string; notification_preferences?: NotificationPreferences; can_invite_staff?: boolean; can_access_tickets?: boolean; permissions?: Record; quota_overages?: QuotaOverage[]; } export type ResourceType = 'STAFF' | 'ROOM' | 'EQUIPMENT'; export type ResourceTypeCategory = 'STAFF' | 'OTHER'; export interface ResourceTypeDefinition { id: string; name: string; // User-facing name like "Stylist", "Massage Therapist", "Treatment Room" description?: string; // Description of this resource type category: ResourceTypeCategory; // STAFF (requires staff assignment) or OTHER isDefault: boolean; // Cannot be deleted iconName?: string; // Optional icon identifier } export interface Resource { id: string; name: string; type: ResourceType; // Legacy field - will be deprecated typeId?: string; // New field - references ResourceTypeDefinition userId?: string; maxConcurrentEvents: number; savedLaneCount?: number; // Remembered lane count when multilane is disabled } export type AppointmentStatus = 'PENDING' | 'CONFIRMED' | 'COMPLETED' | 'CANCELLED' | 'NO_SHOW'; export interface Appointment { id: string; resourceId: string | null; // null if unassigned customerId?: string; // optional for walk-in appointments customerName: string; serviceId: string; startTime: Date; // For MVP, we will assume a specific date durationMinutes: number; status: AppointmentStatus; notes?: string; } export interface Blocker { id: string; resourceId: string; startTime: Date; durationMinutes: number; title: string; } export interface PaymentMethod { id: string; brand: 'Visa' | 'Mastercard' | 'Amex'; last4: string; isDefault: boolean; } export interface Customer { id: string; name: string; email: string; phone: string; city?: string; state?: string; zip?: string; totalSpend: number; lastVisit: Date | null; status: 'Active' | 'Inactive' | 'Blocked'; avatarUrl?: string; tags?: string[]; userId?: string; paymentMethods: PaymentMethod[]; } export interface Service { id: string; name: string; durationMinutes: number; price: number; description: string; displayOrder: number; photos?: string[]; } export interface Metric { label: string; value: string; change: string; trend: 'up' | 'down' | 'neutral'; } // --- Platform Types --- export type TicketType = 'PLATFORM' | 'CUSTOMER' | 'STAFF_REQUEST' | 'INTERNAL'; export type TicketStatus = 'OPEN' | 'IN_PROGRESS' | 'RESOLVED' | 'CLOSED' | 'AWAITING_RESPONSE'; export type TicketPriority = 'LOW' | 'MEDIUM' | 'HIGH' | 'URGENT'; export type TicketCategory = | 'BILLING' | 'TECHNICAL' | 'FEATURE_REQUEST' | 'ACCOUNT' | 'APPOINTMENT' | 'REFUND' | 'COMPLAINT' | 'GENERAL_INQUIRY' | 'TIME_OFF' | 'SCHEDULE_CHANGE' | 'EQUIPMENT' | 'OTHER'; export interface TicketComment { id: string; ticket: string; // Ticket ID author: string; // User ID authorEmail: string; authorFullName: string; commentText: string; createdAt: string; // Date string isInternal: boolean; } export interface TicketEmailAddressListItem { id: number; display_name: string; email_address: string; color: string; is_active: boolean; is_default: boolean; } export interface Ticket { id: string; tenant?: string; // Tenant ID, optional for platform tickets creator: string; // User ID creatorEmail: string; creatorFullName: string; assignee?: string; // User ID, optional assigneeEmail?: string; assigneeFullName?: string; ticketType: TicketType; status: TicketStatus; priority: TicketPriority; subject: string; description: string; category: TicketCategory; relatedAppointmentId?: string; // Appointment ID, optional dueAt?: string; // Date string firstResponseAt?: string; // Date string isOverdue?: boolean; createdAt: string; // Date string updatedAt: string; // Date string resolvedAt?: string; // Date string comments?: TicketComment[]; // Nested comments // External sender info (for tickets from non-registered users via email) externalEmail?: string; externalName?: string; // Source email address (which email address received/sent this ticket) source_email_address?: TicketEmailAddressListItem; } export interface TicketTemplate { id: string; tenant?: string; // Tenant ID, optional for platform templates name: string; description: string; ticketType: TicketType; category: TicketCategory; defaultPriority: TicketPriority; subjectTemplate: string; descriptionTemplate: string; isActive: boolean; createdAt: string; // Date string } export interface CannedResponse { id: string; tenant?: string; // Tenant ID, optional for platform canned responses title: string; content: string; category?: TicketCategory; isActive: boolean; useCount: number; createdBy?: string; // User ID createdAt: string; // Date string } export interface PlatformMetric { label: string; value: string; change: string; trend: 'up' | 'down' | 'neutral'; color: 'blue' | 'green' | 'purple' | 'orange'; } // --- OAuth Settings Types --- export interface OAuthProvider { id: string; name: string; icon: string; description: string; } export interface BusinessOAuthSettings { enabledProviders: string[]; allowRegistration: boolean; autoLinkByEmail: boolean; useCustomCredentials: boolean; } export interface BusinessOAuthSettingsResponse { settings: BusinessOAuthSettings; availableProviders: OAuthProvider[]; } // --- OAuth Credentials Types --- export interface OAuthProviderCredential { client_id: string; client_secret: string; has_secret: boolean; } export interface BusinessOAuthCredentialsResponse { credentials: Record; useCustomCredentials: boolean; } // --- Plugin Types --- export type PluginCategory = 'EMAIL' | 'REPORTS' | 'CUSTOMER' | 'BOOKING' | 'INTEGRATION' | 'AUTOMATION' | 'OTHER'; export interface PluginTemplate { id: string; name: string; description: string; category: PluginCategory; version: string; author: string; logoUrl?: string; pluginCode?: string; rating: number; ratingCount: number; installCount: number; isVerified: boolean; isFeatured: boolean; createdAt: string; updatedAt: string; } export interface PluginInstallation { id: string; template: string; templateName: string; templateDescription: string; category: PluginCategory; version: string; authorName?: string; logoUrl?: string; templateVariables?: Record; configValues?: Record; isActive: boolean; installedAt: string; hasUpdate: boolean; rating?: number; review?: string; scheduledTaskId?: string; } // --- Email Template Types --- export type EmailTemplateScope = 'BUSINESS' | 'PLATFORM'; export type EmailTemplateCategory = | 'APPOINTMENT' | 'REMINDER' | 'CONFIRMATION' | 'MARKETING' | 'NOTIFICATION' | 'REPORT' | 'OTHER'; export interface EmailTemplate { id: string; name: string; description: string; subject: string; htmlContent: string; textContent: string; scope: EmailTemplateScope; isDefault: boolean; category: EmailTemplateCategory; previewContext?: Record; createdBy?: number; createdByName?: string; createdAt: string; updatedAt: string; } export interface EmailTemplatePreview { subject: string; htmlContent: string; textContent: string; forceFooter: boolean; } export interface EmailTemplateVariable { code: string; description: string; } export interface EmailTemplateVariableGroup { category: string; items: EmailTemplateVariable[]; }