// API + config types for the WooCommerce widget. // // Adapted from the Shopify widget. The big difference: quota/ledger enforcement // is handled SERVER-SIDE by the brain storefront gateway, which signals // exhaustion via HTTP 402 and visitor rate-limiting via HTTP 429. The widget no // longer talks to a separate billing API. /** * Response from the brain storefront try-on gateway: * POST {BRAIN_URL}/api/storefront/tryon */ export interface TryOnSyncResponse { image: string; // Base64-encoded PNG cached: boolean; } export interface AvatarData { imageData: string; // Base64 image createdAt: string; } /** * window.AISTHETIX_CONFIG injected by the WordPress plugin. * Kept compatible with the existing global the portable widget reads. */ export interface WidgetConfig { /** Brain storefront try-on endpoint, e.g. https://api.aisthetix.app/api/storefront/tryon */ apiBaseUrl: string; /** Brain base URL, e.g. https://api.aisthetix.app (no trailing slash). */ brainUrl?: string; /** Brain client-event ingestion endpoint, e.g. {brainUrl}/api/events. */ eventsUrl?: string; /** Domain-restricted publishable key — safe for the browser. */ publishableKey: string; /** Garment image URL (mutated by the bootstrap on variation change). */ productImage: string; productTitle: string; productId: string; /** Product category slugs (provider routing). Empty for uncategorized products. */ productCategories?: string[]; siteUrl?: string; /** WooCommerce site locale, e.g. "it_IT". */ locale?: string; /** Logged-in customer id, or null for guests. */ customerId?: string | null; /** * Durable first-party visitor key (the plugin's aisthetix_vid cookie) — the * PRIMARY attribution key. Falls back to the localStorage visitor id when absent. */ visitorKey?: string | null; /** Shopper-safe copy for the short quota/status cache race. */ unavailableMessage?: { title?: string; message?: string; buttonLabel?: string; buttonUrl?: string; }; /** variationId -> image URL map for variable products. */ variationImages?: Record; /** Product page permalink. Used by the demo gallery and the share fallbacks. */ productUrl?: string; // --- Demo-only. Never set on a merchant store. --------------------------- /** * Turns on the aisthetix demo customizations (garment PiP, gallery, remaining * counter, email gate). Only the demo store's own mu-plugin sets this, through * the plugin's public `aisthetix_tryon_config` filter; the plugin itself never * emits it, so every merchant install runs with all of it inert. */ demo?: boolean; /** How many try-ons the demo offers a visitor, for the remaining counter. */ demoTryOnLimit?: number; /** Where the demo posts a captured lead. Absent disables the email gate. */ demoLeadUrl?: string; } /** * One saved try-on, kept in the shopper's own browser (IndexedDB) and never * sent anywhere. Demo-only. */ export interface TryOnHistoryItem { id: string; /** The render, as a data URL. */ resultImage: string; /** The garment, shown as the PiP thumbnail. */ clothingImage?: string; productTitle?: string; productId?: string; productUrl?: string; /** ISO timestamp; also the gallery's newest-first sort key. */ createdAt: string; } /** * The kind of hard-stop the gateway reported, used to choose the blocked view. */ export type BlockedReason = 'quota_exhausted' | 'visitor_rate_limited'; export type WidgetState = | 'idle' | 'avatar-upload' | 'processing' | 'completed' | 'error' | 'quota-exceeded' | 'visitor-rate-limited' /** Demo-only: the saved try-ons. */ | 'gallery' /** Demo-only: the email asked for from the second try-on on. */ | 'lead-gate';