{"version":3,"sources":["../../src/hooks/useSceneBackgroundsPanel.ts"],"names":[],"mappings":"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","file":"useSceneBackgroundsPanel.mjs","sourcesContent":["import { useCallback, useState } from 'react';\nimport type { SceneBackground } from '../types/wall';\nimport { useSceneBackgrounds } from './useSceneBackgrounds';\n\nexport interface UseSceneBackgroundsPanelOptions {\n  /**\n   * UI guard — only enables the setter; the central endpoint enforces auth + ownership\n   * regardless. When false, `submit()` is a no-op so non-admin consumers can render the\n   * primitive read-only.\n   */\n  isAdmin?: boolean;\n  /**\n   * Per-site upload endpoint for the reference photo. Default `/api/uploads/wall-photos`.\n   * Returns `{ url }`.\n   */\n  uploadEndpoint?: string;\n  /**\n   * Centrally hosted generation endpoint. Default `/api/admin/generate-wall-background`.\n   * Auth-required + ownership-guarded. Charges 5 credits per generation.\n   */\n  generateEndpoint?: string;\n  /**\n   * Per-site backgrounds endpoint that lists/creates/deletes rows. Default\n   * `/api/wall-scene-backgrounds`. The POST step is expected to download the\n   * (temporary) Replicate URL into a stable upload schema before persisting.\n   */\n  backgroundsEndpoint?: string;\n}\n\nexport interface SceneBackgroundsPanelState {\n  /** The current list of backgrounds, newest-first. */\n  backgrounds: SceneBackground[];\n  /** Re-fetch the list. */\n  refresh: () => Promise<void>;\n  /** Delete one and refresh. */\n  remove: (id: string) => Promise<void>;\n\n  /** Title field (e.g. \"The Bronx\"). */\n  name: string;\n  setName: (v: string) => void;\n  /** Prompt field — used as the Replicate prompt and stored as the row's description. */\n  description: string;\n  setDescription: (v: string) => void;\n  /** Reference photo. */\n  file: File | null;\n  setFile: (f: File | null) => void;\n\n  /** True when any of upload / generate / save are in flight. */\n  generating: boolean;\n  /** Human-readable progress label, e.g. \"Generating scene with AI…\". */\n  status: string;\n  /** Last error message, or empty string. */\n  error: string;\n\n  /** True when name + description + file are all populated and not currently generating. */\n  canSubmit: boolean;\n  /** Run the full upload → generate → save flow and refresh the list. */\n  submit: () => Promise<void>;\n  /** Clear name + description + file (does not clear the list). */\n  reset: () => void;\n}\n\nconst DEFAULT_UPLOAD = '/api/uploads/wall-photos';\nconst DEFAULT_GENERATE = '/api/admin/generate-wall-background';\nconst DEFAULT_BACKGROUNDS = '/api/wall-scene-backgrounds';\n\n/**\n * Owns the form state + 3-step submission for the scene-background editor:\n *\n *   1. Upload reference photo to `uploadEndpoint` → URL.\n *   2. POST `{ name, description, sourceImageUrl }` to `generateEndpoint`\n *      (centrally credit-metered, returns a Replicate URL).\n *   3. POST `{ name, image_url, description }` to `backgroundsEndpoint`\n *      (the per-site rule downloads the Replicate URL and persists the row).\n *\n * Pair with `<SceneBackgroundsPanel>` for the headless render layer, or wire to\n * your own JSX directly using the returned state.\n */\nexport function useSceneBackgroundsPanel(\n  opts?: UseSceneBackgroundsPanelOptions,\n): SceneBackgroundsPanelState {\n  const uploadEndpoint = opts?.uploadEndpoint ?? DEFAULT_UPLOAD;\n  const generateEndpoint = opts?.generateEndpoint ?? DEFAULT_GENERATE;\n  const backgroundsEndpoint = opts?.backgroundsEndpoint ?? DEFAULT_BACKGROUNDS;\n  const isAdmin = opts?.isAdmin ?? false;\n\n  const sceneBgs = useSceneBackgrounds({ endpoint: backgroundsEndpoint });\n\n  const [name, setName] = useState('');\n  const [description, setDescription] = useState('');\n  const [file, setFile] = useState<File | null>(null);\n  const [generating, setGenerating] = useState(false);\n  const [status, setStatus] = useState('');\n  const [error, setError] = useState('');\n\n  const reset = useCallback(() => {\n    setName('');\n    setDescription('');\n    setFile(null);\n  }, []);\n\n  const remove = useCallback(\n    async (id: string) => {\n      await sceneBgs.remove(id);\n      await sceneBgs.refresh();\n    },\n    [sceneBgs],\n  );\n\n  const submit = useCallback(async () => {\n    if (!isAdmin) return;\n    if (!file || !name.trim() || !description.trim()) return;\n    setError('');\n    setGenerating(true);\n    try {\n      // 1. Upload reference image\n      setStatus('Uploading reference photo…');\n      const fd = new FormData();\n      fd.append('file', file);\n      const upRes = await fetch(uploadEndpoint, {\n        method: 'POST',\n        body: fd,\n        credentials: 'include',\n      });\n      if (!upRes.ok) throw new Error('Upload failed');\n      const upData: { url?: string } = await upRes.json();\n      if (!upData.url) throw new Error('Upload returned no URL');\n      const sourceImageUrl =\n        typeof window !== 'undefined' && !upData.url.startsWith('http')\n          ? window.location.origin + upData.url\n          : upData.url;\n\n      // 2. Generate via central pipeline\n      setStatus('Generating scene with AI…');\n      const genRes = await fetch(generateEndpoint, {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        credentials: 'include',\n        body: JSON.stringify({\n          name: name.trim(),\n          description: description.trim(),\n          sourceImageUrl,\n        }),\n      });\n      if (!genRes.ok) {\n        const errText = await genRes.text();\n        if (errText.includes('NO_CREDITS')) throw new Error('Out of AI credits.');\n        throw new Error('Generation failed.');\n      }\n      const genData: { image_url?: string } = await genRes.json();\n      if (!genData.image_url) throw new Error('Generation returned no image.');\n\n      // 3. Persist row (per-site rule downloads the Replicate URL)\n      setStatus('Saving background…');\n      const saveRes = await fetch(backgroundsEndpoint, {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        credentials: 'include',\n        body: JSON.stringify({\n          name: name.trim(),\n          image_url: genData.image_url,\n          description: description.trim(),\n        }),\n      });\n      if (!saveRes.ok) throw new Error('Failed to save background.');\n\n      await sceneBgs.refresh();\n      reset();\n      setStatus('Done!');\n      setTimeout(() => setStatus(''), 2000);\n    } catch (err) {\n      setError(err instanceof Error ? err.message : 'Something went wrong.');\n      setStatus('');\n    } finally {\n      setGenerating(false);\n    }\n  }, [\n    isAdmin,\n    file,\n    name,\n    description,\n    uploadEndpoint,\n    generateEndpoint,\n    backgroundsEndpoint,\n    sceneBgs,\n    reset,\n  ]);\n\n  const canSubmit =\n    isAdmin && !generating && !!file && name.trim().length > 0 && description.trim().length > 0;\n\n  return {\n    backgrounds: sceneBgs.backgrounds,\n    refresh: sceneBgs.refresh,\n    remove,\n    name,\n    setName,\n    description,\n    setDescription,\n    file,\n    setFile,\n    generating,\n    status,\n    error,\n    canSubmit,\n    submit,\n    reset,\n  };\n}\n"]}