Files
smoothschedule/frontend/src/types.ts
poduck b10426fbdb feat: Add photo galleries to services, resource types management, and UI improvements
Major features:
- Add drag-and-drop photo gallery to Service create/edit modals
- Add Resource Types management section to Settings (CRUD for custom types)
- Add edit icon consistency to Resources table (pencil icon in actions)
- Improve Services page with drag-to-reorder and customer preview mockup

Backend changes:
- Add photos JSONField to Service model with migration
- Add ResourceType model with category (STAFF/OTHER), description fields
- Add ResourceTypeViewSet with CRUD operations
- Add service reorder endpoint for display order

Frontend changes:
- Services page: two-column layout, drag-reorder, photo upload
- Settings page: Resource Types tab with full CRUD modal
- Resources page: Edit icon in actions column instead of row click
- Sidebar: Payments link visibility based on role and paymentsEnabled
- Update types.ts with Service.photos and ResourceTypeDefinition

Note: Removed photos from ResourceType (kept only for Service)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 01:11:53 -05:00

229 lines
5.7 KiB
TypeScript

// 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 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
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;
stripeConnectAccountId?: string;
websitePages?: Record<string, { name: string; content: PageComponent[] }>;
customerDashboardContent?: PageComponent[];
trialStart?: string;
trialEnd?: string;
isTrialActive?: boolean;
isTrialExpired?: boolean;
daysLeftInTrial?: number;
resourceTypes?: ResourceTypeDefinition[]; // Custom resource types
}
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 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;
}
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 interface Ticket {
id: string;
subject: string;
businessName: string;
priority: 'Low' | 'Medium' | 'High' | 'Critical';
status: 'Open' | 'In Progress' | 'Resolved';
createdAt: Date;
}
export interface PlatformMetric {
label: string;
value: string;
change: string;
trend: 'up' | 'down' | 'neutral';
color: 'blue' | 'green' | 'purple' | 'orange';
}
// --- OAuth Settings Types ---
export interface BusinessOAuthSettings {
enabledProviders: string[];
allowRegistration: boolean;
autoLinkByEmail: boolean;
}
export interface BusinessOAuthSettingsResponse {
businessSettings: BusinessOAuthSettings;
availableProviders: string[];
}
// --- OAuth Credentials Types ---
export interface OAuthProviderCredentials {
client_id: string;
client_secret: string;
team_id?: string; // Apple only
key_id?: string; // Apple only
tenant_id?: string; // Microsoft only
}
export interface BusinessOAuthCredentials {
use_custom_credentials: boolean;
google?: OAuthProviderCredentials;
apple?: OAuthProviderCredentials;
facebook?: OAuthProviderCredentials;
linkedin?: OAuthProviderCredentials;
microsoft?: OAuthProviderCredentials;
twitter?: OAuthProviderCredentials;
twitch?: OAuthProviderCredentials;
}