@burdenoff/microfe-hookmovies 2026.720.2 → 2026.726.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hookmovies/hooks/useHookMoviesApi.d.ts +2 -0
- package/dist/hookmovies/hooks/useHookMoviesApi.d.ts.map +1 -1
- package/dist/hookmovies/hooks/useHookMoviesApi.js +17 -3
- package/dist/hookmovies/hooks/useHookMoviesApi.js.map +1 -1
- package/dist/hookmovies/pages/catalog/TitleDetailPage.d.ts.map +1 -1
- package/dist/hookmovies/pages/catalog/TitleDetailPage.js +561 -533
- package/dist/hookmovies/pages/catalog/TitleDetailPage.js.map +1 -1
- package/dist/hookmovies/pages/consumer/PlayerPage.d.ts.map +1 -1
- package/dist/hookmovies/pages/consumer/PlayerPage.js +1 -1
- package/dist/hookmovies/pages/consumer/PlayerPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TitleDetailPage.js","names":[],"sources":["../../../../src/hookmovies/pages/catalog/TitleDetailPage.tsx"],"sourcesContent":["/**\n * Title detail (Catalog)\n * @module hookmovies/pages/catalog\n *\n * Reads a single title via `hokTitle` (with credits, seasons, episodes &\n * studio), and drives the publication lifecycle via `hokTransitionTitle` plus\n * archive via `hokArchiveTitle`. The reviews for the title come from\n * `hokListReviews(titleId)`.\n *\n * Editing surfaces (all inline, tokenized panels):\n * - Edit title metadata (`hokUpdateTitle`, reuses the create-form field set).\n * - Add a cast/crew credit (`hokAddCredit`, person picker with live search).\n * - Add a season / episode for SERIES titles (`hokCreateSeason` / `hokCreateEpisode`).\n * - Watch / mark-as-watched, gated by `hokCheckEntitlement` before recording\n * progress via `hokRecordProgress` (no fake player when not entitled).\n */\n\nimport { type FC, type FormEvent, type ChangeEvent, type ReactNode, useRef, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n Calendar,\n Clock,\n Globe,\n Languages,\n ShieldCheck,\n Sparkles,\n Users,\n Layers,\n Archive,\n Star,\n Pencil,\n UserPlus,\n Plus,\n Play,\n Lock,\n CheckCircle2,\n X,\n Image as ImageIcon,\n Film,\n Clapperboard,\n Video,\n Upload,\n Trash2,\n Loader2,\n type LucideIcon,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { LoadingState, ErrorState } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Pagination } from '../../components/Pagination';\nimport { RatingDisplay } from '../../components/RatingDisplay';\nimport { useHookMovies } from '../../context/HookMoviesContext';\nimport {\n useTitle,\n useTransitionTitle,\n useArchiveTitle,\n useReviews,\n useUpdateTitle,\n useAddCredit,\n useCreateSeason,\n useCreateEpisode,\n useCheckEntitlement,\n useRecordProgress,\n useClips,\n useCreateClip,\n useDeleteClip,\n usePeople,\n useStudios,\n type HokClip,\n type HokCredit,\n type HokTitleDetail,\n type HokTitleStatus,\n type HokTitleType,\n type HokCreditRole,\n type UpdateTitleInput,\n} from '../../hooks/useHookMoviesApi';\nimport { uploadFileToFiles, useFileUrl, FILE_FOLDERS } from '../../hooks/useFiles';\nimport { formatDate, formatEnumLabel } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\n\n/**\n * Publication transitions surfaced as buttons. Mirrors the backend\n * `TITLE_TRANSITIONS` map (catalog.service.ts) exactly, minus `ARCHIVED` —\n * archiving is offered by the dedicated Archive button (via `hokArchiveTitle`)\n * on every non-archived state, so it is intentionally omitted here.\n */\nconst NEXT_STATUSES: Record<HokTitleStatus, HokTitleStatus[]> = {\n DRAFT: ['IN_REVIEW'],\n IN_REVIEW: ['SCHEDULED', 'PUBLISHED', 'DRAFT'],\n SCHEDULED: ['PUBLISHED', 'IN_REVIEW'],\n PUBLISHED: ['UNPUBLISHED'],\n UNPUBLISHED: ['PUBLISHED'],\n ARCHIVED: [],\n};\n\nconst TYPE_OPTIONS: HokTitleType[] = [\n 'MOVIE',\n 'SERIES',\n 'SHORT_FILM',\n 'DOCUMENTARY',\n 'ANIME',\n 'SHORT_FORM',\n 'LONG_FORM',\n 'LIVE_EVENT',\n 'TRAILER',\n 'COLLECTION',\n 'FAST_CHANNEL',\n];\n\nconst CREDIT_ROLE_OPTIONS: HokCreditRole[] = [\n 'ACTOR',\n 'DIRECTOR',\n 'WRITER',\n 'PRODUCER',\n 'CINEMATOGRAPHER',\n 'EDITOR',\n 'COMPOSER',\n 'VOICE_ACTOR',\n 'CREW',\n];\n\nconst fieldClass =\n 'w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]';\nconst labelClass = 'mb-1.5 block text-xs font-medium text-text-secondary';\n\nconst splitCsv = (value: string): string[] =>\n value\n .split(',')\n .map((v) => v.trim())\n .filter(Boolean);\n\n/** Convert a `<input type=\"date\">` value to an ISO DateTime, or undefined when empty. */\nconst dateToIso = (value: string): string | undefined =>\n value.trim() ? new Date(value).toISOString() : undefined;\n\n/** Format a clip's duration (seconds) as `m:ss`. */\nconst formatClipDuration = (seconds: number): string => {\n const m = Math.floor(seconds / 60);\n const s = Math.floor(seconds % 60);\n return `${m}:${s.toString().padStart(2, '0')}`;\n};\n\n// ── Artwork & Media slots ─────────────────────────────────────────────────────\n// The four media refs a title carries. Posters/backdrops are images filed under\n// Artwork; trailer/video masters are video files filed under Masters. Each slot\n// uploads to wspace-files-svc, then persists only the returned file id on the\n// title (this MFE stores no blobs).\ntype MediaField = 'posterFileId' | 'backdropFileId' | 'trailerFileId' | 'videoFileId';\n\ninterface MediaSlotConfig {\n field: MediaField;\n label: string;\n kind: 'image' | 'video';\n folder: string;\n accept: string;\n icon: LucideIcon;\n hint: string;\n}\n\nconst MEDIA_SLOTS: MediaSlotConfig[] = [\n {\n field: 'posterFileId',\n label: 'Poster',\n kind: 'image',\n folder: FILE_FOLDERS.artwork,\n accept: 'image/*',\n icon: ImageIcon,\n hint: 'Vertical key art (2:3).',\n },\n {\n field: 'backdropFileId',\n label: 'Backdrop',\n kind: 'image',\n folder: FILE_FOLDERS.artwork,\n accept: 'image/*',\n icon: ImageIcon,\n hint: 'Wide hero art (16:9).',\n },\n {\n field: 'trailerFileId',\n label: 'Trailer',\n kind: 'video',\n folder: FILE_FOLDERS.masters,\n accept: 'video/*',\n icon: Film,\n hint: 'Promo trailer master.',\n },\n {\n field: 'videoFileId',\n label: 'Video master',\n kind: 'video',\n folder: FILE_FOLDERS.masters,\n accept: 'video/*',\n icon: Clapperboard,\n hint: 'Full-length feature master.',\n },\n];\n\ninterface MediaSlotProps {\n titleId: string;\n config: MediaSlotConfig;\n currentFileId: string | null;\n}\n\n/**\n * A single Artwork/Media upload slot: shows the current file (image thumbnail\n * or inline video), and offers upload / replace / remove. Upload goes through\n * `uploadFileToFiles` (3-step wspace-files) then persists the id on the title\n * via `useUpdateTitle`; remove clears the ref.\n */\nconst MediaSlot: FC<MediaSlotProps> = ({ titleId, config, currentFileId }) => {\n const updateTitle = useUpdateTitle();\n const fileUrl = useFileUrl(currentFileId);\n const inputRef = useRef<HTMLInputElement>(null);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const Icon = config.icon;\n\n const handleSelect = async (e: ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n // Reset the input so the same file can be re-picked after an error.\n e.target.value = '';\n if (!file) return;\n setError(null);\n setBusy(true);\n try {\n const uploaded = await uploadFileToFiles(file, config.folder);\n const input: UpdateTitleInput = {};\n input[config.field] = uploaded.id;\n await updateTitle.mutateAsync({ id: titleId, input });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Upload failed');\n } finally {\n setBusy(false);\n }\n };\n\n const handleRemove = async () => {\n setError(null);\n setBusy(true);\n try {\n // Explicit null clears the column on the backend. UpdateTitleInput types\n // the media fields as optional strings for the common set-path, so this\n // single clear payload is cast.\n const input = { [config.field]: null } as UpdateTitleInput;\n await updateTitle.mutateAsync({ id: titleId, input });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Could not remove file');\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <div className=\"rounded-xl border border-border-seam bg-bg-surface p-4\">\n <div className=\"mb-3 flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2\">\n <Icon className=\"h-4 w-4 text-text-secondary\" />\n <h3 className=\"text-sm font-medium text-text-primary\">{config.label}</h3>\n </div>\n {currentFileId && (\n <span className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[10px] font-medium text-status-success-text\">\n Set\n </span>\n )}\n </div>\n\n <div\n className={cn(\n 'relative flex items-center justify-center overflow-hidden rounded-lg border border-border-subtle bg-bg-sunken',\n config.kind === 'image' ? 'aspect-[3/4]' : 'aspect-video'\n )}\n >\n {busy ? (\n <div className=\"flex flex-col items-center gap-2 text-text-secondary\">\n <Loader2 className=\"h-6 w-6 animate-spin\" />\n <span className=\"text-xs\">Uploading…</span>\n </div>\n ) : currentFileId ? (\n fileUrl.isLoading ? (\n <Loader2 className=\"h-6 w-6 animate-spin text-text-secondary\" />\n ) : fileUrl.data ? (\n config.kind === 'image' ? (\n <img\n src={fileUrl.data}\n alt={`${config.label} artwork`}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <video\n src={fileUrl.data}\n controls\n preload=\"metadata\"\n className=\"h-full w-full bg-bg-canvas object-contain\"\n >\n <track kind=\"captions\" />\n </video>\n )\n ) : (\n <div className=\"flex flex-col items-center gap-1 text-text-secondary\">\n <Icon className=\"h-6 w-6\" />\n <span className=\"text-xs\">Preview unavailable</span>\n </div>\n )\n ) : (\n <button\n type=\"button\"\n onClick={() => inputRef.current?.click()}\n className=\"flex h-full w-full flex-col items-center justify-center gap-2 text-text-secondary transition-colors hover:text-text-primary\"\n >\n <Upload className=\"h-6 w-6\" />\n <span className=\"text-xs\">Upload {config.label.toLowerCase()}</span>\n </button>\n )}\n </div>\n\n <p className=\"mt-2 text-[11px] text-text-secondary\">{config.hint}</p>\n\n {error && <p className=\"mt-2 text-xs text-status-error-text\">{error}</p>}\n\n <div className=\"mt-3 flex items-center gap-2\">\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => inputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-2.5 py-1 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50\"\n >\n <Upload className=\"h-3.5 w-3.5\" />\n {currentFileId ? 'Replace' : 'Upload'}\n </button>\n {currentFileId && (\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => void handleRemove()}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-status-error-border px-2.5 py-1 text-xs font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n Remove\n </button>\n )}\n </div>\n\n <input\n ref={inputRef}\n type=\"file\"\n accept={config.accept}\n className=\"hidden\"\n onChange={(e) => void handleSelect(e)}\n aria-label={`Upload ${config.label}`}\n />\n </div>\n );\n};\n\ninterface ClipCardProps {\n clip: HokClip;\n onDelete: (clip: HokClip) => void;\n deleting: boolean;\n}\n\n/** A single clip tile: vertical poster (or inline video) + caption/meta + delete. */\nconst ClipCard: FC<ClipCardProps> = ({ clip, onDelete, deleting }) => {\n const posterUrl = useFileUrl(clip.posterFileId);\n // Only resolve the video URL when there is no poster to preview.\n const videoUrl = useFileUrl(clip.posterFileId ? undefined : clip.videoFileId);\n\n return (\n <div className=\"flex flex-col overflow-hidden rounded-xl border border-border-seam bg-bg-surface\">\n <div className=\"relative aspect-[9/16] w-full overflow-hidden bg-bg-sunken\">\n {clip.posterFileId ? (\n posterUrl.isLoading ? (\n <div className=\"flex h-full w-full items-center justify-center\">\n <Loader2 className=\"h-5 w-5 animate-spin text-text-secondary\" />\n </div>\n ) : posterUrl.data ? (\n <img\n src={posterUrl.data}\n alt={clip.caption ?? 'Clip poster'}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"flex h-full w-full items-center justify-center text-text-secondary\">\n <Film className=\"h-6 w-6\" />\n </div>\n )\n ) : videoUrl.isLoading ? (\n <div className=\"flex h-full w-full items-center justify-center\">\n <Loader2 className=\"h-5 w-5 animate-spin text-text-secondary\" />\n </div>\n ) : videoUrl.data ? (\n <video\n src={videoUrl.data}\n controls\n preload=\"metadata\"\n className=\"h-full w-full bg-bg-canvas object-contain\"\n >\n <track kind=\"captions\" />\n </video>\n ) : (\n <div className=\"flex h-full w-full items-center justify-center text-text-secondary\">\n <Film className=\"h-6 w-6\" />\n </div>\n )}\n {clip.durationSeconds != null && (\n <span className=\"absolute bottom-2 right-2 rounded bg-bg-canvas/80 px-1.5 py-0.5 text-[10px] font-medium text-text-primary\">\n {formatClipDuration(clip.durationSeconds)}\n </span>\n )}\n </div>\n <div className=\"flex flex-1 flex-col gap-2 p-3\">\n <p className=\"line-clamp-2 text-sm text-text-primary\">{clip.caption ?? 'Untitled clip'}</p>\n {clip.language && (\n <span className=\"w-fit rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] uppercase tracking-wide text-text-secondary\">\n {clip.language}\n </span>\n )}\n <button\n type=\"button\"\n disabled={deleting}\n onClick={() => onDelete(clip)}\n className=\"mt-auto inline-flex items-center justify-center gap-1.5 rounded-lg border border-status-error-border px-2.5 py-1 text-xs font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n {deleting ? 'Deleting…' : 'Delete'}\n </button>\n </div>\n </div>\n );\n};\n\n/**\n * A consistent panel header: an icon in a tokenized chip, a title, an optional\n * count pill, and optional right-aligned actions. Wraps gracefully on mobile.\n */\nconst PanelHeader: FC<{\n icon: LucideIcon;\n title: string;\n count?: number;\n actions?: ReactNode;\n}> = ({ icon: Icon, title, count, actions }) => (\n <div className=\"mb-4 flex flex-wrap items-center justify-between gap-3\">\n <h2 className=\"flex items-center gap-2.5 text-sm font-semibold text-text-primary\">\n <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary\">\n <Icon className=\"h-4 w-4\" />\n </span>\n <span>{title}</span>\n {count !== undefined && (\n <span className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {count}\n </span>\n )}\n </h2>\n {actions && <div className=\"flex flex-wrap items-center gap-2\">{actions}</div>}\n </div>\n);\n\n/** Up-to-two-letter initials for a person avatar fallback (no photo field exists). */\nconst initials = (name: string): string =>\n name\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((part) => part[0]?.toUpperCase() ?? '')\n .join('') || '?';\n\n/** A single Cast & Crew tile: initials avatar + name + character + role chip. */\nconst CreditTile: FC<{ credit: HokCredit }> = ({ credit }) => {\n const name = credit.person?.name ?? 'Unknown person';\n return (\n <div className=\"flex flex-col items-center gap-2 rounded-xl border border-border-seam bg-bg-surface p-3 text-center transition-colors hover:border-border-strong\">\n <span\n className=\"flex h-14 w-14 items-center justify-center rounded-full bg-bg-sunken text-sm font-semibold text-text-secondary\"\n aria-hidden=\"true\"\n >\n {initials(name)}\n </span>\n <div className=\"w-full min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{name}</p>\n {credit.characterName && (\n <p className=\"truncate text-xs text-text-secondary\">as {credit.characterName}</p>\n )}\n </div>\n <span className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-text-secondary\">\n {formatEnumLabel(credit.role)}\n </span>\n </div>\n );\n};\n\n/**\n * Cinematic title header: a backdrop band (with a tokenized mesh fallback), an\n * overlapping poster card, plus type/studio, quick-fact chips, genres and the\n * synopsis — all resolved from the real title record + `useFileUrl`.\n */\nconst TitleHero: FC<{ title: HokTitleDetail }> = ({ title }) => {\n const backdrop = useFileUrl(title.backdropFileId);\n const poster = useFileUrl(title.posterFileId);\n\n const metaChips: Array<{ icon: LucideIcon; label: string }> = [];\n if (title.releaseDate) metaChips.push({ icon: Calendar, label: formatDate(title.releaseDate) });\n else if (title.releaseYear) metaChips.push({ icon: Calendar, label: String(title.releaseYear) });\n if (title.runtimeMinutes) metaChips.push({ icon: Clock, label: `${title.runtimeMinutes} min` });\n if (title.originalLanguage) metaChips.push({ icon: Languages, label: title.originalLanguage });\n if (title.originCountry) metaChips.push({ icon: Globe, label: title.originCountry });\n if (title.certification) metaChips.push({ icon: ShieldCheck, label: title.certification });\n\n return (\n <GlassCard treatment=\"insight\" className=\"mb-6 overflow-hidden border-border-seam p-0\">\n {/* Backdrop band */}\n <div className=\"relative h-28 w-full overflow-hidden bg-bg-sunken sm:h-40 lg:h-48\">\n {backdrop.isLoading ? (\n <div className=\"flex h-full w-full items-center justify-center\">\n <Loader2 className=\"h-5 w-5 animate-spin text-text-secondary\" />\n </div>\n ) : backdrop.data ? (\n <img src={backdrop.data} alt=\"\" className=\"h-full w-full object-cover\" />\n ) : (\n <div className=\"h-full w-full bg-hero-mesh\" />\n )}\n <div className=\"absolute inset-0 bg-gradient-to-t from-bg-surface via-bg-surface/70 to-transparent\" />\n </div>\n\n {/* Poster + meta */}\n <div className=\"flex flex-col gap-4 px-5 pb-5 sm:flex-row sm:gap-5\">\n <div className=\"-mt-14 w-24 shrink-0 sm:-mt-24 sm:w-36\">\n <div className=\"aspect-[2/3] overflow-hidden rounded-xl border border-border-seam bg-bg-sunken shadow-elevation-2\">\n {poster.isLoading ? (\n <div className=\"flex h-full w-full items-center justify-center\">\n <Loader2 className=\"h-5 w-5 animate-spin text-text-secondary\" />\n </div>\n ) : poster.data ? (\n <img\n src={poster.data}\n alt={`${title.title} poster`}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"flex h-full w-full flex-col items-center justify-center gap-1 text-text-secondary\">\n <ImageIcon className=\"h-6 w-6\" />\n <span className=\"text-[10px]\">No poster</span>\n </div>\n )}\n </div>\n </div>\n\n <div className=\"min-w-0 flex-1 pt-1 sm:pt-4\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {formatEnumLabel(title.type)}\n {title.studio ? ` · ${title.studio.name}` : ''}\n </p>\n\n {(metaChips.length > 0 || title.aiDisclosure) && (\n <div className=\"mt-3 flex flex-wrap gap-2\">\n {metaChips.map((chip) => {\n const Icon = chip.icon;\n return (\n <span\n key={chip.label}\n className=\"inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-2.5 py-1 text-xs text-text-secondary\"\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {chip.label}\n </span>\n );\n })}\n {title.aiDisclosure && (\n <span className=\"inline-flex items-center gap-1.5 rounded-full bg-status-info-bg-subtle px-2.5 py-1 text-xs text-status-info-text\">\n <Sparkles className=\"h-3.5 w-3.5\" />\n AI-assisted\n </span>\n )}\n </div>\n )}\n\n {title.genres.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1.5\">\n {title.genres.map((g) => (\n <span\n key={g}\n className=\"rounded-full border border-border-seam px-2.5 py-0.5 text-xs text-text-primary\"\n >\n {g}\n </span>\n ))}\n </div>\n )}\n\n {title.synopsis && (\n <p className=\"mt-4 max-w-3xl text-sm leading-relaxed text-text-secondary\">\n {title.synopsis}\n </p>\n )}\n </div>\n </div>\n </GlassCard>\n );\n};\n\nconst CLIP_PAGE_SIZE = 12;\n\nexport const TitleDetailPage: FC = () => {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useHookMovies();\n const { data: title, isLoading, isError, refetch } = useTitle(id);\n const transition = useTransitionTitle();\n const archive = useArchiveTitle();\n const reviews = useReviews({ titleId: id }, { limit: 10, offset: 0 });\n const updateTitle = useUpdateTitle();\n const addCredit = useAddCredit();\n const createSeason = useCreateSeason();\n const createEpisode = useCreateEpisode();\n const recordProgress = useRecordProgress();\n const entitlement = useCheckEntitlement(id);\n const studios = useStudios({ limit: 200, offset: 0 });\n\n // ── Clips (short-form promos attached to the title) ────────────────────────\n const [clipPage, setClipPage] = useState(0);\n const clips = useClips(id, undefined, {\n limit: CLIP_PAGE_SIZE,\n offset: clipPage * CLIP_PAGE_SIZE,\n });\n const createClip = useCreateClip();\n const deleteClip = useDeleteClip();\n\n const [actionError, setActionError] = useState<string | null>(null);\n\n // ── Add-clip form state ─────────────────────────────────────────────────────\n const [showClipForm, setShowClipForm] = useState(false);\n const [clipFile, setClipFile] = useState<File | null>(null);\n const [clipCaption, setClipCaption] = useState('');\n const [clipDuration, setClipDuration] = useState('');\n const [clipLanguage, setClipLanguage] = useState('');\n const [clipUploading, setClipUploading] = useState(false);\n const [clipError, setClipError] = useState<string | null>(null);\n const [deletingClipId, setDeletingClipId] = useState<string | null>(null);\n const clipInputRef = useRef<HTMLInputElement>(null);\n\n // ── Which inline panel (if any) is open ────────────────────────────────────\n const [openPanel, setOpenPanel] = useState<'none' | 'edit' | 'credit' | 'season' | 'episode'>(\n 'none'\n );\n\n // ── Edit-title form state ──────────────────────────────────────────────────\n const [eTitle, setETitle] = useState('');\n const [eType, setEType] = useState<HokTitleType>('MOVIE');\n const [eSynopsis, setESynopsis] = useState('');\n const [eGenres, setEGenres] = useState('');\n const [eTags, setETags] = useState('');\n const [eLanguage, setELanguage] = useState('');\n const [eCountry, setECountry] = useState('');\n const [eYear, setEYear] = useState('');\n const [eRuntime, setERuntime] = useState('');\n const [eCertification, setECertification] = useState('');\n const [eStudioId, setEStudioId] = useState('');\n const [eAiDisclosure, setEAiDisclosure] = useState(false);\n\n // ── Add-credit form state ──────────────────────────────────────────────────\n const [personSearch, setPersonSearch] = useState('');\n const [creditPersonId, setCreditPersonId] = useState('');\n const [creditRole, setCreditRole] = useState<HokCreditRole>('ACTOR');\n const [creditCharacter, setCreditCharacter] = useState('');\n const [creditBilling, setCreditBilling] = useState('');\n const people = usePeople({ limit: 50, offset: 0 }, personSearch);\n\n // ── Add-season form state ──────────────────────────────────────────────────\n const [seasonNumber, setSeasonNumber] = useState('');\n const [seasonName, setSeasonName] = useState('');\n const [seasonSynopsis, setSeasonSynopsis] = useState('');\n const [seasonAirDate, setSeasonAirDate] = useState('');\n\n // ── Add-episode form state ─────────────────────────────────────────────────\n const [episodeSeasonId, setEpisodeSeasonId] = useState('');\n const [episodeNumber, setEpisodeNumber] = useState('');\n const [episodeName, setEpisodeName] = useState('');\n const [episodeSynopsis, setEpisodeSynopsis] = useState('');\n const [episodeRuntime, setEpisodeRuntime] = useState('');\n const [episodeAirDate, setEpisodeAirDate] = useState('');\n\n const [watchedNotice, setWatchedNotice] = useState(false);\n\n if (isLoading) {\n return (\n <PageLayout title=\"Title\">\n <LoadingState label=\"Loading title…\" />\n </PageLayout>\n );\n }\n\n if (isError || !title) {\n return (\n <PageLayout title=\"Title\">\n <ErrorState\n title=\"Title not found\"\n message=\"This title may have been archived or you may not have access.\"\n onRetry={() => void refetch()}\n />\n </PageLayout>\n );\n }\n\n const isSeries = title.type === 'SERIES';\n\n const closePanel = () => setOpenPanel('none');\n\n const openEdit = () => {\n setActionError(null);\n setETitle(title.title);\n setEType(title.type);\n setESynopsis(title.synopsis ?? '');\n setEGenres(title.genres.join(', '));\n setETags(title.tags.join(', '));\n setELanguage(title.originalLanguage ?? '');\n setECountry(title.originCountry ?? '');\n setEYear(title.releaseYear ? String(title.releaseYear) : '');\n setERuntime(title.runtimeMinutes ? String(title.runtimeMinutes) : '');\n setECertification(title.certification ?? '');\n setEStudioId(title.studioId ?? '');\n setEAiDisclosure(title.aiDisclosure);\n setOpenPanel('edit');\n };\n\n const handleTransition = async (status: HokTitleStatus) => {\n setActionError(null);\n try {\n await transition.mutateAsync({ id: title.id, status });\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Transition failed');\n }\n };\n\n const handleArchive = async () => {\n setActionError(null);\n try {\n await archive.mutateAsync(title.id);\n navigateTo('catalog/titles');\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Archive failed');\n }\n };\n\n const handleEditSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setActionError(null);\n if (!eTitle.trim()) {\n setActionError('Title is required.');\n return;\n }\n const input: UpdateTitleInput = {\n title: eTitle.trim(),\n type: eType,\n synopsis: eSynopsis.trim() || undefined,\n genres: splitCsv(eGenres),\n tags: splitCsv(eTags),\n originalLanguage: eLanguage.trim() || undefined,\n originCountry: eCountry.trim() || undefined,\n releaseYear: eYear.trim() ? Number(eYear) : undefined,\n runtimeMinutes: eRuntime.trim() ? Number(eRuntime) : undefined,\n certification: eCertification.trim() || undefined,\n studioId: eStudioId || undefined,\n aiDisclosure: eAiDisclosure,\n };\n try {\n await updateTitle.mutateAsync({ id: title.id, input });\n closePanel();\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to update title');\n }\n };\n\n const handleCreditSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setActionError(null);\n if (!creditPersonId) {\n setActionError('Select a person to credit.');\n return;\n }\n try {\n await addCredit.mutateAsync({\n personId: creditPersonId,\n titleId: title.id,\n role: creditRole,\n characterName: creditCharacter.trim() || undefined,\n billingOrder: creditBilling.trim() ? Number(creditBilling) : undefined,\n });\n setCreditPersonId('');\n setCreditCharacter('');\n setCreditBilling('');\n setPersonSearch('');\n closePanel();\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to add credit');\n }\n };\n\n const handleSeasonSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setActionError(null);\n if (!seasonNumber.trim()) {\n setActionError('Season number is required.');\n return;\n }\n try {\n await createSeason.mutateAsync({\n titleId: title.id,\n number: Number(seasonNumber),\n name: seasonName.trim() || undefined,\n synopsis: seasonSynopsis.trim() || undefined,\n airDate: dateToIso(seasonAirDate),\n });\n setSeasonNumber('');\n setSeasonName('');\n setSeasonSynopsis('');\n setSeasonAirDate('');\n closePanel();\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to add season');\n }\n };\n\n const handleEpisodeSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setActionError(null);\n if (!episodeNumber.trim()) {\n setActionError('Episode number is required.');\n return;\n }\n if (!episodeName.trim()) {\n setActionError('Episode name is required.');\n return;\n }\n try {\n await createEpisode.mutateAsync({\n titleId: title.id,\n number: Number(episodeNumber),\n name: episodeName.trim(),\n seasonId: episodeSeasonId || undefined,\n synopsis: episodeSynopsis.trim() || undefined,\n runtimeMinutes: episodeRuntime.trim() ? Number(episodeRuntime) : undefined,\n airDate: dateToIso(episodeAirDate),\n });\n setEpisodeSeasonId('');\n setEpisodeNumber('');\n setEpisodeName('');\n setEpisodeSynopsis('');\n setEpisodeRuntime('');\n setEpisodeAirDate('');\n closePanel();\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to add episode');\n }\n };\n\n const handleMarkWatched = async () => {\n setActionError(null);\n setWatchedNotice(false);\n if (!entitlement.data?.entitled) {\n setActionError('You are not entitled to watch this title.');\n return;\n }\n try {\n await recordProgress.mutateAsync({\n titleId: title.id,\n positionSeconds: (title.runtimeMinutes ?? 0) * 60,\n completed: true,\n lastDevice: 'web',\n });\n setWatchedNotice(true);\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to record progress');\n }\n };\n\n const handleClipSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setClipError(null);\n if (!clipFile) {\n setClipError('Select a clip video to upload.');\n return;\n }\n setClipUploading(true);\n try {\n const uploaded = await uploadFileToFiles(clipFile, FILE_FOLDERS.clips);\n await createClip.mutateAsync({\n titleId: title.id,\n videoFileId: uploaded.id,\n caption: clipCaption.trim() || undefined,\n durationSeconds: clipDuration.trim() ? Number(clipDuration) : undefined,\n language: clipLanguage.trim() || undefined,\n });\n setClipFile(null);\n setClipCaption('');\n setClipDuration('');\n setClipLanguage('');\n if (clipInputRef.current) clipInputRef.current.value = '';\n setShowClipForm(false);\n setClipPage(0);\n } catch (err) {\n setClipError(err instanceof Error ? err.message : 'Failed to add clip');\n } finally {\n setClipUploading(false);\n }\n };\n\n const handleClipDelete = async (clip: HokClip) => {\n setActionError(null);\n setDeletingClipId(clip.id);\n try {\n await deleteClip.mutateAsync({ id: clip.id, titleId: title.id });\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to delete clip');\n } finally {\n setDeletingClipId(null);\n }\n };\n\n const reviewItems = reviews.data?.items ?? [];\n const clipItems = clips.data?.items ?? [];\n const avgScore =\n reviewItems.length > 0\n ? reviewItems.reduce((sum, r) => sum + r.score, 0) / reviewItems.length\n : null;\n\n const facts: Array<{ icon: typeof Calendar; label: string; value: string }> = [];\n if (title.releaseDate)\n facts.push({ icon: Calendar, label: 'Release', value: formatDate(title.releaseDate) });\n else if (title.releaseYear)\n facts.push({ icon: Calendar, label: 'Year', value: String(title.releaseYear) });\n if (title.runtimeMinutes)\n facts.push({ icon: Clock, label: 'Runtime', value: `${title.runtimeMinutes} min` });\n if (title.originalLanguage)\n facts.push({ icon: Languages, label: 'Language', value: title.originalLanguage });\n if (title.originCountry)\n facts.push({ icon: Globe, label: 'Country', value: title.originCountry });\n if (title.certification)\n facts.push({ icon: ShieldCheck, label: 'Certification', value: title.certification });\n\n const peopleItems = people.data?.items ?? [];\n\n return (\n <PageLayout\n title={\n <span className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigateTo('catalog/titles')}\n className=\"rounded-md p-1 text-text-secondary hover:text-text-primary\"\n aria-label=\"Back to catalog\"\n >\n <ArrowLeft className=\"h-5 w-5\" />\n </button>\n {title.title}\n </span>\n }\n description={`${formatEnumLabel(title.type)}${title.studio ? ` · ${title.studio.name}` : ''}`}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={openEdit}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-seam px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n Edit\n </button>\n <StatusBadge status={title.status} />\n </div>\n }\n >\n {actionError && (\n <div className=\"mb-4 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text\">\n {actionError}\n </div>\n )}\n\n {/* Cinematic backdrop / poster header (art + synopsis + quick facts) */}\n <TitleHero title={title} />\n\n {/* Edit-title panel (full-width; reuses the create-form field set) */}\n {openPanel === 'edit' && (\n <GlassCard treatment=\"metric\" className=\"mb-6 border-border-seam p-5\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-sm font-semibold text-text-primary\">Edit title</h2>\n <button\n type=\"button\"\n onClick={closePanel}\n className=\"rounded-md p-1 text-text-secondary hover:text-text-primary\"\n aria-label=\"Close edit form\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n <form onSubmit={handleEditSubmit} className=\"space-y-5\">\n <div>\n <label htmlFor=\"edit-title\" className={labelClass}>\n Title *\n </label>\n <input\n id=\"edit-title\"\n type=\"text\"\n value={eTitle}\n onChange={(e) => setETitle(e.target.value)}\n className={fieldClass}\n required\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"edit-type\" className={labelClass}>\n Type\n </label>\n <select\n id=\"edit-type\"\n value={eType}\n onChange={(e) => setEType(e.target.value as HokTitleType)}\n className={fieldClass}\n >\n {TYPE_OPTIONS.map((t) => (\n <option key={t} value={t}>\n {formatEnumLabel(t)}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"edit-studio\" className={labelClass}>\n Studio\n </label>\n <select\n id=\"edit-studio\"\n value={eStudioId}\n onChange={(e) => setEStudioId(e.target.value)}\n className={fieldClass}\n >\n <option value=\"\">No studio</option>\n {(studios.data?.items ?? []).map((s) => (\n <option key={s.id} value={s.id}>\n {s.name}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n <div>\n <label htmlFor=\"edit-synopsis\" className={labelClass}>\n Synopsis\n </label>\n <textarea\n id=\"edit-synopsis\"\n value={eSynopsis}\n onChange={(e) => setESynopsis(e.target.value)}\n rows={4}\n className={fieldClass}\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"edit-genres\" className={labelClass}>\n Genres (comma-separated)\n </label>\n <input\n id=\"edit-genres\"\n type=\"text\"\n value={eGenres}\n onChange={(e) => setEGenres(e.target.value)}\n placeholder=\"Drama, Thriller\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"edit-tags\" className={labelClass}>\n Tags (comma-separated)\n </label>\n <input\n id=\"edit-tags\"\n type=\"text\"\n value={eTags}\n onChange={(e) => setETags(e.target.value)}\n placeholder=\"award-winner, indie\"\n className={fieldClass}\n />\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <div>\n <label htmlFor=\"edit-language\" className={labelClass}>\n Original Language\n </label>\n <input\n id=\"edit-language\"\n type=\"text\"\n value={eLanguage}\n onChange={(e) => setELanguage(e.target.value)}\n placeholder=\"en\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"edit-country\" className={labelClass}>\n Origin Country\n </label>\n <input\n id=\"edit-country\"\n type=\"text\"\n value={eCountry}\n onChange={(e) => setECountry(e.target.value)}\n placeholder=\"US\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"edit-certification\" className={labelClass}>\n Certification\n </label>\n <input\n id=\"edit-certification\"\n type=\"text\"\n value={eCertification}\n onChange={(e) => setECertification(e.target.value)}\n placeholder=\"PG-13\"\n className={fieldClass}\n />\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"edit-year\" className={labelClass}>\n Release Year\n </label>\n <input\n id=\"edit-year\"\n type=\"number\"\n value={eYear}\n onChange={(e) => setEYear(e.target.value)}\n placeholder=\"2026\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"edit-runtime\" className={labelClass}>\n Runtime (minutes)\n </label>\n <input\n id=\"edit-runtime\"\n type=\"number\"\n value={eRuntime}\n onChange={(e) => setERuntime(e.target.value)}\n placeholder=\"120\"\n className={fieldClass}\n />\n </div>\n </div>\n\n <label className=\"flex items-center gap-2 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={eAiDisclosure}\n onChange={(e) => setEAiDisclosure(e.target.checked)}\n className=\"h-4 w-4 rounded border-border-subtle\"\n />\n This title contains AI-generated or AI-altered content\n </label>\n\n <div className=\"flex items-center gap-3 pt-1\">\n <button\n type=\"submit\"\n disabled={updateTitle.isPending}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n {updateTitle.isPending ? 'Saving…' : 'Save changes'}\n </button>\n <button\n type=\"button\"\n onClick={closePanel}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n </GlassCard>\n )}\n\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Main column */}\n <div className=\"space-y-6 lg:col-span-2\">\n {/* Artwork & Media */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <PanelHeader icon={ImageIcon} title=\"Artwork & Media\" />\n <p className=\"-mt-2 mb-4 text-xs text-text-secondary\">\n Poster and backdrop art, plus the trailer and full-length video master. Files are\n stored in the workspace files service; the title keeps only a reference.\n </p>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n {MEDIA_SLOTS.map((slot) => (\n <MediaSlot\n key={slot.field}\n titleId={title.id}\n config={slot}\n currentFileId={title[slot.field]}\n />\n ))}\n </div>\n </GlassCard>\n\n {/* Credits */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <PanelHeader\n icon={Users}\n title=\"Cast & Crew\"\n count={title.credits.length}\n actions={\n <button\n type=\"button\"\n onClick={() => {\n setActionError(null);\n setOpenPanel(openPanel === 'credit' ? 'none' : 'credit');\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-2.5 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <UserPlus className=\"h-3.5 w-3.5\" />\n Add credit\n </button>\n }\n />\n\n {openPanel === 'credit' && (\n <form\n onSubmit={handleCreditSubmit}\n className=\"mb-4 space-y-4 rounded-lg border border-border-seam bg-bg-surface p-4\"\n >\n <div>\n <label htmlFor=\"credit-search\" className={labelClass}>\n Search people\n </label>\n <input\n id=\"credit-search\"\n type=\"text\"\n value={personSearch}\n onChange={(e) => setPersonSearch(e.target.value)}\n placeholder=\"Type a name to filter…\"\n className={fieldClass}\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"credit-person\" className={labelClass}>\n Person *\n </label>\n <select\n id=\"credit-person\"\n value={creditPersonId}\n onChange={(e) => setCreditPersonId(e.target.value)}\n className={fieldClass}\n required\n >\n <option value=\"\">\n {people.isLoading\n ? 'Loading people…'\n : peopleItems.length === 0\n ? 'No people found'\n : 'Select a person'}\n </option>\n {peopleItems.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n {p.knownFor ? ` — ${p.knownFor}` : ''}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"credit-role\" className={labelClass}>\n Role\n </label>\n <select\n id=\"credit-role\"\n value={creditRole}\n onChange={(e) => setCreditRole(e.target.value as HokCreditRole)}\n className={fieldClass}\n >\n {CREDIT_ROLE_OPTIONS.map((r) => (\n <option key={r} value={r}>\n {formatEnumLabel(r)}\n </option>\n ))}\n </select>\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"credit-character\" className={labelClass}>\n Character name\n </label>\n <input\n id=\"credit-character\"\n type=\"text\"\n value={creditCharacter}\n onChange={(e) => setCreditCharacter(e.target.value)}\n placeholder=\"e.g. Captain Rao\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"credit-billing\" className={labelClass}>\n Billing order\n </label>\n <input\n id=\"credit-billing\"\n type=\"number\"\n value={creditBilling}\n onChange={(e) => setCreditBilling(e.target.value)}\n placeholder=\"1\"\n className={fieldClass}\n />\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n <button\n type=\"submit\"\n disabled={addCredit.isPending}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n <Plus className=\"h-4 w-4\" />\n {addCredit.isPending ? 'Adding…' : 'Add credit'}\n </button>\n <button\n type=\"button\"\n onClick={closePanel}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n )}\n\n {title.credits.length === 0 ? (\n <EmptyState\n title=\"No credits recorded yet\"\n description=\"Add the cast and crew who worked on this title.\"\n />\n ) : (\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4\">\n {[...title.credits]\n .sort((a, b) => a.billingOrder - b.billingOrder)\n .map((credit) => (\n <CreditTile key={credit.id} credit={credit} />\n ))}\n <button\n type=\"button\"\n onClick={() => {\n setActionError(null);\n setOpenPanel(openPanel === 'credit' ? 'none' : 'credit');\n }}\n className=\"flex min-h-[9.5rem] flex-col items-center justify-center gap-2 rounded-xl border border-dashed border-border-seam bg-bg-surface p-3 text-text-secondary transition-colors hover:border-border-strong hover:text-text-primary\"\n >\n <span className=\"flex h-10 w-10 items-center justify-center rounded-full bg-bg-sunken\">\n <UserPlus className=\"h-5 w-5\" />\n </span>\n <span className=\"text-xs font-medium\">Add credit</span>\n </button>\n </div>\n )}\n </GlassCard>\n\n {/* Seasons & episodes */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <PanelHeader\n icon={Layers}\n title=\"Episodes\"\n count={title.episodes.length}\n actions={\n isSeries ? (\n <>\n <button\n type=\"button\"\n onClick={() => {\n setActionError(null);\n setOpenPanel(openPanel === 'season' ? 'none' : 'season');\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-2.5 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n Add season\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActionError(null);\n setOpenPanel(openPanel === 'episode' ? 'none' : 'episode');\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-2.5 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n Add episode\n </button>\n </>\n ) : undefined\n }\n />\n\n {isSeries && openPanel === 'season' && (\n <form\n onSubmit={handleSeasonSubmit}\n className=\"mb-4 space-y-4 rounded-lg border border-border-seam bg-bg-surface p-4\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"season-number\" className={labelClass}>\n Season number *\n </label>\n <input\n id=\"season-number\"\n type=\"number\"\n value={seasonNumber}\n onChange={(e) => setSeasonNumber(e.target.value)}\n placeholder=\"1\"\n className={fieldClass}\n required\n />\n </div>\n <div>\n <label htmlFor=\"season-name\" className={labelClass}>\n Name\n </label>\n <input\n id=\"season-name\"\n type=\"text\"\n value={seasonName}\n onChange={(e) => setSeasonName(e.target.value)}\n placeholder=\"Season 1\"\n className={fieldClass}\n />\n </div>\n </div>\n <div>\n <label htmlFor=\"season-synopsis\" className={labelClass}>\n Synopsis\n </label>\n <textarea\n id=\"season-synopsis\"\n value={seasonSynopsis}\n onChange={(e) => setSeasonSynopsis(e.target.value)}\n rows={3}\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"season-airdate\" className={labelClass}>\n Air date\n </label>\n <input\n id=\"season-airdate\"\n type=\"date\"\n value={seasonAirDate}\n onChange={(e) => setSeasonAirDate(e.target.value)}\n className={fieldClass}\n />\n </div>\n <div className=\"flex items-center gap-3\">\n <button\n type=\"submit\"\n disabled={createSeason.isPending}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n <Plus className=\"h-4 w-4\" />\n {createSeason.isPending ? 'Adding…' : 'Add season'}\n </button>\n <button\n type=\"button\"\n onClick={closePanel}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n )}\n\n {isSeries && openPanel === 'episode' && (\n <form\n onSubmit={handleEpisodeSubmit}\n className=\"mb-4 space-y-4 rounded-lg border border-border-seam bg-bg-surface p-4\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"episode-season\" className={labelClass}>\n Season\n </label>\n <select\n id=\"episode-season\"\n value={episodeSeasonId}\n onChange={(e) => setEpisodeSeasonId(e.target.value)}\n className={fieldClass}\n >\n <option value=\"\">No season</option>\n {[...title.seasons]\n .sort((a, b) => a.number - b.number)\n .map((s) => (\n <option key={s.id} value={s.id}>\n {s.name ? `${s.number}. ${s.name}` : `Season ${s.number}`}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"episode-number\" className={labelClass}>\n Episode number *\n </label>\n <input\n id=\"episode-number\"\n type=\"number\"\n value={episodeNumber}\n onChange={(e) => setEpisodeNumber(e.target.value)}\n placeholder=\"1\"\n className={fieldClass}\n required\n />\n </div>\n </div>\n <div>\n <label htmlFor=\"episode-name\" className={labelClass}>\n Name *\n </label>\n <input\n id=\"episode-name\"\n type=\"text\"\n value={episodeName}\n onChange={(e) => setEpisodeName(e.target.value)}\n placeholder=\"Pilot\"\n className={fieldClass}\n required\n />\n </div>\n <div>\n <label htmlFor=\"episode-synopsis\" className={labelClass}>\n Synopsis\n </label>\n <textarea\n id=\"episode-synopsis\"\n value={episodeSynopsis}\n onChange={(e) => setEpisodeSynopsis(e.target.value)}\n rows={3}\n className={fieldClass}\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"episode-runtime\" className={labelClass}>\n Runtime (minutes)\n </label>\n <input\n id=\"episode-runtime\"\n type=\"number\"\n value={episodeRuntime}\n onChange={(e) => setEpisodeRuntime(e.target.value)}\n placeholder=\"45\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"episode-airdate\" className={labelClass}>\n Air date\n </label>\n <input\n id=\"episode-airdate\"\n type=\"date\"\n value={episodeAirDate}\n onChange={(e) => setEpisodeAirDate(e.target.value)}\n className={fieldClass}\n />\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n <button\n type=\"submit\"\n disabled={createEpisode.isPending}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n <Plus className=\"h-4 w-4\" />\n {createEpisode.isPending ? 'Adding…' : 'Add episode'}\n </button>\n <button\n type=\"button\"\n onClick={closePanel}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n )}\n\n {title.episodes.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {isSeries\n ? 'No episodes yet. Add a season, then episodes, to build out this series.'\n : 'No episodes recorded for this title.'}\n </p>\n ) : (\n <ul className=\"space-y-1\">\n {[...title.episodes]\n .sort((a, b) => a.number - b.number)\n .map((ep) => (\n <li\n key={ep.id}\n className=\"flex items-center gap-3 rounded-lg px-2 py-2 transition-colors hover:bg-bg-sunken\"\n >\n <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-bg-sunken text-xs font-semibold text-text-secondary\">\n {ep.number}\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{ep.name}</p>\n {ep.synopsis && (\n <p className=\"line-clamp-1 text-xs text-text-secondary\">{ep.synopsis}</p>\n )}\n </div>\n {ep.runtimeMinutes && (\n <span className=\"shrink-0 text-xs text-text-secondary\">\n {ep.runtimeMinutes} min\n </span>\n )}\n </li>\n ))}\n </ul>\n )}\n </GlassCard>\n\n {/* Reviews */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <PanelHeader icon={Star} title=\"Reviews\" count={reviewItems.length} />\n {reviewItems.length === 0 ? (\n <EmptyState\n title=\"No reviews yet\"\n description=\"Reviews from verified viewers will appear here.\"\n />\n ) : (\n <>\n {avgScore !== null && (\n <div className=\"mb-4 flex items-center gap-4 rounded-xl border border-border-seam bg-bg-surface p-4\">\n <div className=\"flex flex-col items-center\">\n <span className=\"text-3xl font-semibold leading-none text-text-primary\">\n {avgScore.toFixed(1)}\n </span>\n <span className=\"mt-1 text-[10px] uppercase tracking-wide text-text-secondary\">\n / 10\n </span>\n </div>\n <div className=\"min-w-0\">\n <RatingDisplay value={avgScore / 2} count={reviewItems.length} size=\"md\" />\n <p className=\"mt-1 text-xs text-text-secondary\">\n Average across {reviewItems.length}{' '}\n {reviewItems.length === 1 ? 'review' : 'reviews'}\n </p>\n </div>\n </div>\n )}\n <ul className=\"space-y-3\">\n {reviewItems.map((review) => (\n <li\n key={review.id}\n className=\"rounded-lg border border-border-seam bg-bg-surface p-3\"\n >\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-semibold text-text-primary\">\n {review.score}/10\n </span>\n <div className=\"flex items-center gap-2\">\n {review.verifiedWatch && (\n <span className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[10px] text-status-success-text\">\n Verified\n </span>\n )}\n <StatusBadge status={review.status} />\n </div>\n </div>\n {review.body && (\n <p className=\"mt-1 text-sm text-text-secondary\">{review.body}</p>\n )}\n </li>\n ))}\n </ul>\n </>\n )}\n </GlassCard>\n\n {/* Clips */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <PanelHeader\n icon={Video}\n title=\"Clips\"\n count={clips.data?.totalCount ?? clipItems.length}\n actions={\n <button\n type=\"button\"\n onClick={() => {\n setClipError(null);\n setShowClipForm((v) => !v);\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-2.5 py-1 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n Add clip\n </button>\n }\n />\n\n {showClipForm && (\n <form\n onSubmit={handleClipSubmit}\n className=\"mb-4 space-y-4 rounded-lg border border-border-seam bg-bg-surface p-4\"\n >\n <div>\n <label htmlFor=\"clip-file\" className={labelClass}>\n Clip video * (short vertical MP4)\n </label>\n <input\n id=\"clip-file\"\n ref={clipInputRef}\n type=\"file\"\n accept=\"video/*\"\n onChange={(e) => setClipFile(e.target.files?.[0] ?? null)}\n className={fieldClass}\n />\n {clipFile && (\n <p className=\"mt-1 truncate text-xs text-text-secondary\">\n Selected: {clipFile.name}\n </p>\n )}\n </div>\n <div>\n <label htmlFor=\"clip-caption\" className={labelClass}>\n Caption\n </label>\n <input\n id=\"clip-caption\"\n type=\"text\"\n value={clipCaption}\n onChange={(e) => setClipCaption(e.target.value)}\n placeholder=\"e.g. Official teaser\"\n className={fieldClass}\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"clip-duration\" className={labelClass}>\n Duration (seconds)\n </label>\n <input\n id=\"clip-duration\"\n type=\"number\"\n min={0}\n value={clipDuration}\n onChange={(e) => setClipDuration(e.target.value)}\n placeholder=\"30\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"clip-language\" className={labelClass}>\n Language\n </label>\n <input\n id=\"clip-language\"\n type=\"text\"\n value={clipLanguage}\n onChange={(e) => setClipLanguage(e.target.value)}\n placeholder=\"en\"\n className={fieldClass}\n />\n </div>\n </div>\n {clipError && <p className=\"text-xs text-status-error-text\">{clipError}</p>}\n <div className=\"flex items-center gap-3\">\n <button\n type=\"submit\"\n disabled={clipUploading}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-opacity hover:opacity-90 disabled:opacity-50\"\n >\n <Upload className=\"h-4 w-4\" />\n {clipUploading ? 'Uploading…' : 'Add clip'}\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setShowClipForm(false);\n setClipError(null);\n }}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n </div>\n </form>\n )}\n\n {clips.isLoading ? (\n <LoadingState label=\"Loading clips…\" className=\"min-h-[20vh]\" />\n ) : clips.isError ? (\n <ErrorState\n title=\"Could not load clips\"\n message=\"Something went wrong fetching this title's clips.\"\n onRetry={() => void clips.refetch()}\n className=\"min-h-[20vh]\"\n />\n ) : clipItems.length === 0 ? (\n <EmptyState\n title=\"No clips yet\"\n description=\"Upload a short vertical clip to promote this title.\"\n />\n ) : (\n <>\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4\">\n {clipItems.map((clip) => (\n <ClipCard\n key={clip.id}\n clip={clip}\n deleting={deletingClipId === clip.id}\n onDelete={(c) => void handleClipDelete(c)}\n />\n ))}\n </div>\n <Pagination\n page={clipPage}\n hasMore={clips.data?.pageInfo.hasMore ?? false}\n shownCount={clipItems.length}\n onPageChange={setClipPage}\n />\n </>\n )}\n </GlassCard>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Watch / entitlement */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Play className=\"h-4 w-4\" />\n Watch\n </h2>\n {entitlement.isLoading ? (\n <p className=\"text-sm text-text-secondary\">Checking access…</p>\n ) : entitlement.isError ? (\n <div className=\"space-y-2\">\n <p className=\"text-sm text-status-error-text\">Could not check entitlement.</p>\n <button\n type=\"button\"\n onClick={() => void entitlement.refetch()}\n className=\"rounded-lg border border-border-seam px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Retry\n </button>\n </div>\n ) : entitlement.data?.entitled ? (\n <div className=\"space-y-3\">\n {entitlement.data.modes.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {entitlement.data.modes.map((mode) => (\n <span\n key={mode}\n className=\"rounded-full bg-status-success-bg-subtle px-2.5 py-0.5 text-xs text-status-success-text\"\n >\n {formatEnumLabel(mode)}\n </span>\n ))}\n </div>\n )}\n {watchedNotice ? (\n <p className=\"flex items-center gap-2 text-sm text-status-success-text\">\n <CheckCircle2 className=\"h-4 w-4\" />\n Marked as watched — see Continue Watching.\n </p>\n ) : (\n <button\n type=\"button\"\n disabled={recordProgress.isPending}\n onClick={() => void handleMarkWatched()}\n className=\"inline-flex w-full items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n <Play className=\"h-4 w-4\" />\n {recordProgress.isPending ? 'Saving…' : 'Mark as watched'}\n </button>\n )}\n </div>\n ) : (\n <div className=\"flex items-start gap-2 rounded-lg border border-border-seam bg-bg-sunken px-3 py-2.5\">\n <Lock className=\"mt-0.5 h-4 w-4 shrink-0 text-text-secondary\" />\n <p className=\"text-sm text-text-secondary\">\n You are not entitled to watch this title. Grant an entitlement or add a rights\n window to enable playback.\n </p>\n </div>\n )}\n </GlassCard>\n\n {/* Lifecycle actions */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-3 text-sm font-semibold text-text-primary\">Publication</h2>\n <div className=\"flex flex-wrap gap-2\">\n {NEXT_STATUSES[title.status].map((status) => (\n <button\n key={status}\n type=\"button\"\n disabled={transition.isPending}\n onClick={() => void handleTransition(status)}\n className=\"rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n {formatEnumLabel(status)}\n </button>\n ))}\n {NEXT_STATUSES[title.status].length === 0 && (\n <p className=\"text-xs text-text-secondary\">No further transitions available.</p>\n )}\n </div>\n {title.status !== 'ARCHIVED' && (\n <button\n type=\"button\"\n disabled={archive.isPending}\n onClick={() => void handleArchive()}\n className=\"mt-3 inline-flex items-center gap-2 rounded-lg border border-status-error-border px-3 py-1.5 text-xs font-medium text-status-error-text hover:bg-status-error-bg-subtle disabled:opacity-50 transition-colors\"\n >\n <Archive className=\"h-3.5 w-3.5\" />\n Archive Title\n </button>\n )}\n </GlassCard>\n\n {/* Facts */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-3 text-sm font-semibold text-text-primary\">Details</h2>\n <dl className=\"space-y-2\">\n {facts.map((fact) => {\n const Icon = fact.icon;\n return (\n <div key={fact.label} className=\"flex items-center justify-between text-sm\">\n <dt className=\"flex items-center gap-2 text-text-secondary\">\n <Icon className=\"h-3.5 w-3.5\" />\n {fact.label}\n </dt>\n <dd className=\"font-medium text-text-primary\">{fact.value}</dd>\n </div>\n );\n })}\n {title.aiDisclosure && (\n <div className=\"flex items-center gap-2 pt-1 text-sm text-text-secondary\">\n <Sparkles className=\"h-3.5 w-3.5\" />\n Contains AI-generated content\n </div>\n )}\n </dl>\n </GlassCard>\n\n {/* Genres & tags */}\n {(title.genres.length > 0 || title.tags.length > 0) && (\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n {title.genres.length > 0 && (\n <>\n <h3 className=\"mb-2 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n Genres\n </h3>\n <div className=\"mb-3 flex flex-wrap gap-1.5\">\n {title.genres.map((g) => (\n <span\n key={g}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-primary\"\n >\n {g}\n </span>\n ))}\n </div>\n </>\n )}\n {title.tags.length > 0 && (\n <>\n <h3 className=\"mb-2 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n Tags\n </h3>\n <div className=\"flex flex-wrap gap-1.5\">\n {title.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n </>\n )}\n </GlassCard>\n )}\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TitleDetailPage.js","names":[],"sources":["../../../../src/hookmovies/pages/catalog/TitleDetailPage.tsx"],"sourcesContent":["/**\n * Title detail (Catalog)\n * @module hookmovies/pages/catalog\n *\n * Reads a single title via `hokTitle` (with credits, seasons, episodes &\n * studio), and drives the publication lifecycle via `hokTransitionTitle` plus\n * archive via `hokArchiveTitle`. The reviews for the title come from\n * `hokListReviews(titleId)`.\n *\n * Editing surfaces (all inline, tokenized panels):\n * - Edit title metadata (`hokUpdateTitle`, reuses the create-form field set).\n * - Add a cast/crew credit (`hokAddCredit`, person picker with live search).\n * - Add a season / episode for SERIES titles (`hokCreateSeason` / `hokCreateEpisode`).\n * - Watch / mark-as-watched, gated by `hokCheckEntitlement` before recording\n * progress via `hokRecordProgress` (no fake player when not entitled).\n */\n\nimport { type FC, type FormEvent, type ChangeEvent, type ReactNode, useRef, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n Calendar,\n Clock,\n Globe,\n Languages,\n ShieldCheck,\n Sparkles,\n Users,\n Layers,\n Archive,\n Star,\n Pencil,\n UserPlus,\n Plus,\n Play,\n Lock,\n CheckCircle2,\n X,\n Image as ImageIcon,\n Film,\n Clapperboard,\n Video,\n Upload,\n Trash2,\n Loader2,\n type LucideIcon,\n} from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { LoadingState, ErrorState } from '../../components/StateViews';\nimport { EmptyState } from '../../components/EmptyState';\nimport { Pagination } from '../../components/Pagination';\nimport { RatingDisplay } from '../../components/RatingDisplay';\nimport { useHookMovies } from '../../context/HookMoviesContext';\nimport {\n useTitle,\n useTransitionTitle,\n useArchiveTitle,\n useReviews,\n useUpdateTitle,\n useAddCredit,\n useCreateSeason,\n useCreateEpisode,\n useCheckEntitlement,\n useRecordProgress,\n useClips,\n useCreateClip,\n useDeleteClip,\n usePeople,\n useStudios,\n type HokClip,\n type HokCredit,\n type HokTitleDetail,\n type HokTitleStatus,\n type HokTitleType,\n type HokCreditRole,\n type UpdateTitleInput,\n} from '../../hooks/useHookMoviesApi';\nimport { uploadFileToFiles, useFileUrl, FILE_FOLDERS } from '../../hooks/useFiles';\nimport { formatDate, formatEnumLabel } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\n\n/**\n * Publication transitions surfaced as buttons. Mirrors the backend\n * `TITLE_TRANSITIONS` map (catalog.service.ts) exactly, minus `ARCHIVED` —\n * archiving is offered by the dedicated Archive button (via `hokArchiveTitle`)\n * on every non-archived state, so it is intentionally omitted here.\n */\nconst NEXT_STATUSES: Record<HokTitleStatus, HokTitleStatus[]> = {\n DRAFT: ['IN_REVIEW'],\n IN_REVIEW: ['SCHEDULED', 'PUBLISHED', 'DRAFT'],\n SCHEDULED: ['PUBLISHED', 'IN_REVIEW'],\n PUBLISHED: ['UNPUBLISHED'],\n UNPUBLISHED: ['PUBLISHED'],\n ARCHIVED: [],\n};\n\nconst TYPE_OPTIONS: HokTitleType[] = [\n 'MOVIE',\n 'SERIES',\n 'SHORT_FILM',\n 'DOCUMENTARY',\n 'ANIME',\n 'SHORT_FORM',\n 'LONG_FORM',\n 'LIVE_EVENT',\n 'TRAILER',\n 'COLLECTION',\n 'FAST_CHANNEL',\n];\n\nconst CREDIT_ROLE_OPTIONS: HokCreditRole[] = [\n 'ACTOR',\n 'DIRECTOR',\n 'WRITER',\n 'PRODUCER',\n 'CINEMATOGRAPHER',\n 'EDITOR',\n 'COMPOSER',\n 'VOICE_ACTOR',\n 'CREW',\n];\n\nconst fieldClass =\n 'w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]';\nconst labelClass = 'mb-1.5 block text-xs font-medium text-text-secondary';\n\nconst splitCsv = (value: string): string[] =>\n value\n .split(',')\n .map((v) => v.trim())\n .filter(Boolean);\n\n/** Convert a `<input type=\"date\">` value to an ISO DateTime, or undefined when empty. */\nconst dateToIso = (value: string): string | undefined =>\n value.trim() ? new Date(value).toISOString() : undefined;\n\n/** Format a clip's duration (seconds) as `m:ss`. */\nconst formatClipDuration = (seconds: number): string => {\n const m = Math.floor(seconds / 60);\n const s = Math.floor(seconds % 60);\n return `${m}:${s.toString().padStart(2, '0')}`;\n};\n\n// ── Artwork & Media slots ─────────────────────────────────────────────────────\n// The four media refs a title carries. Posters/backdrops are images filed under\n// Artwork; trailer/video masters are video files filed under Masters. Each slot\n// uploads to wspace-files-svc, then persists only the returned file id on the\n// title (this MFE stores no blobs).\ntype MediaField = 'posterFileId' | 'backdropFileId' | 'trailerFileId' | 'videoFileId';\n\ninterface MediaSlotConfig {\n field: MediaField;\n label: string;\n kind: 'image' | 'video';\n folder: string;\n accept: string;\n icon: LucideIcon;\n hint: string;\n}\n\nconst MEDIA_SLOTS: MediaSlotConfig[] = [\n {\n field: 'posterFileId',\n label: 'Poster',\n kind: 'image',\n folder: FILE_FOLDERS.artwork,\n accept: 'image/*',\n icon: ImageIcon,\n hint: 'Vertical key art (2:3).',\n },\n {\n field: 'backdropFileId',\n label: 'Backdrop',\n kind: 'image',\n folder: FILE_FOLDERS.artwork,\n accept: 'image/*',\n icon: ImageIcon,\n hint: 'Wide hero art (16:9).',\n },\n {\n field: 'trailerFileId',\n label: 'Trailer',\n kind: 'video',\n folder: FILE_FOLDERS.masters,\n accept: 'video/*',\n icon: Film,\n hint: 'Promo trailer master.',\n },\n {\n field: 'videoFileId',\n label: 'Video master',\n kind: 'video',\n folder: FILE_FOLDERS.masters,\n accept: 'video/*',\n icon: Clapperboard,\n hint: 'Full-length feature master.',\n },\n];\n\ninterface MediaSlotProps {\n titleId: string;\n config: MediaSlotConfig;\n currentFileId: string | null;\n}\n\n/**\n * A single Artwork/Media upload slot: shows the current file (image thumbnail\n * or inline video), and offers upload / replace / remove. Upload goes through\n * `uploadFileToFiles` (3-step wspace-files) then persists the id on the title\n * via `useUpdateTitle`; remove clears the ref.\n */\nconst MediaSlot: FC<MediaSlotProps> = ({ titleId, config, currentFileId }) => {\n const updateTitle = useUpdateTitle();\n const fileUrl = useFileUrl(currentFileId);\n const inputRef = useRef<HTMLInputElement>(null);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const Icon = config.icon;\n\n const handleSelect = async (e: ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n // Reset the input so the same file can be re-picked after an error.\n e.target.value = '';\n if (!file) return;\n setError(null);\n setBusy(true);\n try {\n const uploaded = await uploadFileToFiles(file, config.folder);\n const input: UpdateTitleInput = {};\n input[config.field] = uploaded.id;\n await updateTitle.mutateAsync({ id: titleId, input });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Upload failed');\n } finally {\n setBusy(false);\n }\n };\n\n const handleRemove = async () => {\n setError(null);\n setBusy(true);\n try {\n // Explicit null clears the column on the backend. UpdateTitleInput types\n // the media fields as optional strings for the common set-path, so this\n // single clear payload is cast.\n const input = { [config.field]: null } as UpdateTitleInput;\n await updateTitle.mutateAsync({ id: titleId, input });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Could not remove file');\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <div className=\"rounded-xl border border-border-seam bg-bg-surface p-4\">\n <div className=\"mb-3 flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-2\">\n <Icon className=\"h-4 w-4 text-text-secondary\" />\n <h3 className=\"text-sm font-medium text-text-primary\">{config.label}</h3>\n </div>\n {currentFileId && (\n <span className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[10px] font-medium text-status-success-text\">\n Set\n </span>\n )}\n </div>\n\n <div\n className={cn(\n 'relative flex items-center justify-center overflow-hidden rounded-lg border border-border-subtle bg-bg-sunken',\n config.kind === 'image' ? 'aspect-[3/4]' : 'aspect-video'\n )}\n >\n {busy ? (\n <div className=\"flex flex-col items-center gap-2 text-text-secondary\">\n <Loader2 className=\"h-6 w-6 animate-spin\" />\n <span className=\"text-xs\">Uploading…</span>\n </div>\n ) : currentFileId ? (\n fileUrl.isLoading ? (\n <Loader2 className=\"h-6 w-6 animate-spin text-text-secondary\" />\n ) : fileUrl.data ? (\n config.kind === 'image' ? (\n <img\n src={fileUrl.data}\n alt={`${config.label} artwork`}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <video\n src={fileUrl.data}\n controls\n preload=\"metadata\"\n className=\"h-full w-full bg-bg-canvas object-contain\"\n >\n <track kind=\"captions\" />\n </video>\n )\n ) : (\n <div className=\"flex flex-col items-center gap-1 text-text-secondary\">\n <Icon className=\"h-6 w-6\" />\n <span className=\"text-xs\">Preview unavailable</span>\n </div>\n )\n ) : (\n <button\n type=\"button\"\n onClick={() => inputRef.current?.click()}\n className=\"flex h-full w-full flex-col items-center justify-center gap-2 text-text-secondary transition-colors hover:text-text-primary\"\n >\n <Upload className=\"h-6 w-6\" />\n <span className=\"text-xs\">Upload {config.label.toLowerCase()}</span>\n </button>\n )}\n </div>\n\n <p className=\"mt-2 text-[11px] text-text-secondary\">{config.hint}</p>\n\n {error && <p className=\"mt-2 text-xs text-status-error-text\">{error}</p>}\n\n <div className=\"mt-3 flex items-center gap-2\">\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => inputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-2.5 py-1 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50\"\n >\n <Upload className=\"h-3.5 w-3.5\" />\n {currentFileId ? 'Replace' : 'Upload'}\n </button>\n {currentFileId && (\n <button\n type=\"button\"\n disabled={busy}\n onClick={() => void handleRemove()}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-status-error-border px-2.5 py-1 text-xs font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n Remove\n </button>\n )}\n </div>\n\n <input\n ref={inputRef}\n type=\"file\"\n accept={config.accept}\n className=\"hidden\"\n onChange={(e) => void handleSelect(e)}\n aria-label={`Upload ${config.label}`}\n />\n </div>\n );\n};\n\ninterface ClipCardProps {\n clip: HokClip;\n onDelete: (clip: HokClip) => void;\n deleting: boolean;\n}\n\n/** A single clip tile: vertical poster (or inline video) + caption/meta + delete. */\nconst ClipCard: FC<ClipCardProps> = ({ clip, onDelete, deleting }) => {\n const posterUrl = useFileUrl(clip.posterFileId);\n // Only resolve the video URL when there is no poster to preview.\n const videoUrl = useFileUrl(clip.posterFileId ? undefined : clip.videoFileId);\n\n return (\n <div className=\"flex flex-col overflow-hidden rounded-xl border border-border-seam bg-bg-surface\">\n <div className=\"relative aspect-[9/16] w-full overflow-hidden bg-bg-sunken\">\n {clip.posterFileId ? (\n posterUrl.isLoading ? (\n <div className=\"flex h-full w-full items-center justify-center\">\n <Loader2 className=\"h-5 w-5 animate-spin text-text-secondary\" />\n </div>\n ) : posterUrl.data ? (\n <img\n src={posterUrl.data}\n alt={clip.caption ?? 'Clip poster'}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"flex h-full w-full items-center justify-center text-text-secondary\">\n <Film className=\"h-6 w-6\" />\n </div>\n )\n ) : videoUrl.isLoading ? (\n <div className=\"flex h-full w-full items-center justify-center\">\n <Loader2 className=\"h-5 w-5 animate-spin text-text-secondary\" />\n </div>\n ) : videoUrl.data ? (\n <video\n src={videoUrl.data}\n controls\n preload=\"metadata\"\n className=\"h-full w-full bg-bg-canvas object-contain\"\n >\n <track kind=\"captions\" />\n </video>\n ) : (\n <div className=\"flex h-full w-full items-center justify-center text-text-secondary\">\n <Film className=\"h-6 w-6\" />\n </div>\n )}\n {clip.durationSeconds != null && (\n <span className=\"absolute bottom-2 right-2 rounded bg-bg-canvas/80 px-1.5 py-0.5 text-[10px] font-medium text-text-primary\">\n {formatClipDuration(clip.durationSeconds)}\n </span>\n )}\n </div>\n <div className=\"flex flex-1 flex-col gap-2 p-3\">\n <p className=\"line-clamp-2 text-sm text-text-primary\">{clip.caption ?? 'Untitled clip'}</p>\n {clip.language && (\n <span className=\"w-fit rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] uppercase tracking-wide text-text-secondary\">\n {clip.language}\n </span>\n )}\n <button\n type=\"button\"\n disabled={deleting}\n onClick={() => onDelete(clip)}\n className=\"mt-auto inline-flex items-center justify-center gap-1.5 rounded-lg border border-status-error-border px-2.5 py-1 text-xs font-medium text-status-error-text transition-colors hover:bg-status-error-bg-subtle disabled:opacity-50\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n {deleting ? 'Deleting…' : 'Delete'}\n </button>\n </div>\n </div>\n );\n};\n\n/**\n * A consistent panel header: an icon in a tokenized chip, a title, an optional\n * count pill, and optional right-aligned actions. Wraps gracefully on mobile.\n */\nconst PanelHeader: FC<{\n icon: LucideIcon;\n title: string;\n count?: number;\n actions?: ReactNode;\n}> = ({ icon: Icon, title, count, actions }) => (\n <div className=\"mb-4 flex flex-wrap items-center justify-between gap-3\">\n <h2 className=\"flex items-center gap-2.5 text-sm font-semibold text-text-primary\">\n <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-bg-sunken text-text-secondary\">\n <Icon className=\"h-4 w-4\" />\n </span>\n <span>{title}</span>\n {count !== undefined && (\n <span className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {count}\n </span>\n )}\n </h2>\n {actions && <div className=\"flex flex-wrap items-center gap-2\">{actions}</div>}\n </div>\n);\n\n/** Up-to-two-letter initials for a person avatar fallback (no photo field exists). */\nconst initials = (name: string): string =>\n name\n .split(/\\s+/)\n .filter(Boolean)\n .slice(0, 2)\n .map((part) => part[0]?.toUpperCase() ?? '')\n .join('') || '?';\n\n/** A single Cast & Crew tile: initials avatar + name + character + role chip. */\nconst CreditTile: FC<{ credit: HokCredit }> = ({ credit }) => {\n const name = credit.person?.name ?? 'Unknown person';\n return (\n <div className=\"flex flex-col items-center gap-2 rounded-xl border border-border-seam bg-bg-surface p-3 text-center transition-colors hover:border-border-strong\">\n <span\n className=\"flex h-14 w-14 items-center justify-center rounded-full bg-bg-sunken text-sm font-semibold text-text-secondary\"\n aria-hidden=\"true\"\n >\n {initials(name)}\n </span>\n <div className=\"w-full min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{name}</p>\n {credit.characterName && (\n <p className=\"truncate text-xs text-text-secondary\">as {credit.characterName}</p>\n )}\n </div>\n <span className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-text-secondary\">\n {formatEnumLabel(credit.role)}\n </span>\n </div>\n );\n};\n\n/**\n * Cinematic title header: a backdrop band (with a tokenized mesh fallback), an\n * overlapping poster card, plus type/studio, quick-fact chips, genres and the\n * synopsis — all resolved from the real title record + `useFileUrl`.\n */\nconst TitleHero: FC<{ title: HokTitleDetail }> = ({ title }) => {\n const backdrop = useFileUrl(title.backdropFileId);\n const poster = useFileUrl(title.posterFileId);\n\n const metaChips: Array<{ icon: LucideIcon; label: string }> = [];\n if (title.releaseDate) metaChips.push({ icon: Calendar, label: formatDate(title.releaseDate) });\n else if (title.releaseYear) metaChips.push({ icon: Calendar, label: String(title.releaseYear) });\n if (title.runtimeMinutes) metaChips.push({ icon: Clock, label: `${title.runtimeMinutes} min` });\n if (title.originalLanguage) metaChips.push({ icon: Languages, label: title.originalLanguage });\n if (title.originCountry) metaChips.push({ icon: Globe, label: title.originCountry });\n if (title.certification) metaChips.push({ icon: ShieldCheck, label: title.certification });\n\n return (\n <GlassCard treatment=\"insight\" className=\"mb-6 overflow-hidden border-border-seam p-0\">\n {/* Backdrop band */}\n <div className=\"relative h-28 w-full overflow-hidden bg-bg-sunken sm:h-40 lg:h-48\">\n {backdrop.isLoading ? (\n <div className=\"flex h-full w-full items-center justify-center\">\n <Loader2 className=\"h-5 w-5 animate-spin text-text-secondary\" />\n </div>\n ) : backdrop.data ? (\n <img src={backdrop.data} alt=\"\" className=\"h-full w-full object-cover\" />\n ) : (\n <div className=\"h-full w-full bg-hero-mesh\" />\n )}\n <div className=\"absolute inset-0 bg-gradient-to-t from-bg-surface via-bg-surface/70 to-transparent\" />\n </div>\n\n {/* Poster + meta */}\n <div className=\"flex flex-col gap-4 px-5 pb-5 sm:flex-row sm:gap-5\">\n <div className=\"-mt-14 w-24 shrink-0 sm:-mt-24 sm:w-36\">\n <div className=\"aspect-[2/3] overflow-hidden rounded-xl border border-border-seam bg-bg-sunken shadow-elevation-2\">\n {poster.isLoading ? (\n <div className=\"flex h-full w-full items-center justify-center\">\n <Loader2 className=\"h-5 w-5 animate-spin text-text-secondary\" />\n </div>\n ) : poster.data ? (\n <img\n src={poster.data}\n alt={`${title.title} poster`}\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div className=\"flex h-full w-full flex-col items-center justify-center gap-1 text-text-secondary\">\n <ImageIcon className=\"h-6 w-6\" />\n <span className=\"text-[10px]\">No poster</span>\n </div>\n )}\n </div>\n </div>\n\n <div className=\"min-w-0 flex-1 pt-1 sm:pt-4\">\n <p className=\"text-xs font-medium uppercase tracking-wide text-text-secondary\">\n {formatEnumLabel(title.type)}\n {title.studio ? ` · ${title.studio.name}` : ''}\n </p>\n\n {(metaChips.length > 0 || title.aiDisclosure) && (\n <div className=\"mt-3 flex flex-wrap gap-2\">\n {metaChips.map((chip) => {\n const Icon = chip.icon;\n return (\n <span\n key={chip.label}\n className=\"inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-2.5 py-1 text-xs text-text-secondary\"\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {chip.label}\n </span>\n );\n })}\n {title.aiDisclosure && (\n <span className=\"inline-flex items-center gap-1.5 rounded-full bg-status-info-bg-subtle px-2.5 py-1 text-xs text-status-info-text\">\n <Sparkles className=\"h-3.5 w-3.5\" />\n AI-assisted\n </span>\n )}\n </div>\n )}\n\n {title.genres.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1.5\">\n {title.genres.map((g) => (\n <span\n key={g}\n className=\"rounded-full border border-border-seam px-2.5 py-0.5 text-xs text-text-primary\"\n >\n {g}\n </span>\n ))}\n </div>\n )}\n\n {title.synopsis && (\n <p className=\"mt-4 max-w-3xl text-sm leading-relaxed text-text-secondary\">\n {title.synopsis}\n </p>\n )}\n </div>\n </div>\n </GlassCard>\n );\n};\n\nconst CLIP_PAGE_SIZE = 12;\n\nexport const TitleDetailPage: FC = () => {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useHookMovies();\n const { data: title, isLoading, isError, refetch } = useTitle(id);\n const transition = useTransitionTitle();\n const archive = useArchiveTitle();\n const reviews = useReviews({ titleId: id }, { limit: 10, offset: 0 });\n const updateTitle = useUpdateTitle();\n const addCredit = useAddCredit();\n const createSeason = useCreateSeason();\n const createEpisode = useCreateEpisode();\n const recordProgress = useRecordProgress();\n const entitlement = useCheckEntitlement(id);\n const studios = useStudios({ limit: 200, offset: 0 });\n\n // ── Clips (short-form promos attached to the title) ────────────────────────\n const [clipPage, setClipPage] = useState(0);\n const clips = useClips(id, undefined, {\n limit: CLIP_PAGE_SIZE,\n offset: clipPage * CLIP_PAGE_SIZE,\n });\n const createClip = useCreateClip();\n const deleteClip = useDeleteClip();\n\n const [actionError, setActionError] = useState<string | null>(null);\n\n // ── Add-clip form state ─────────────────────────────────────────────────────\n const [showClipForm, setShowClipForm] = useState(false);\n const [clipFile, setClipFile] = useState<File | null>(null);\n const [clipCaption, setClipCaption] = useState('');\n const [clipDuration, setClipDuration] = useState('');\n const [clipLanguage, setClipLanguage] = useState('');\n const [clipUploading, setClipUploading] = useState(false);\n const [clipError, setClipError] = useState<string | null>(null);\n const [deletingClipId, setDeletingClipId] = useState<string | null>(null);\n const clipInputRef = useRef<HTMLInputElement>(null);\n\n // ── Which inline panel (if any) is open ────────────────────────────────────\n const [openPanel, setOpenPanel] = useState<'none' | 'edit' | 'credit' | 'season' | 'episode'>(\n 'none'\n );\n\n // ── Edit-title form state ──────────────────────────────────────────────────\n const [eTitle, setETitle] = useState('');\n const [eType, setEType] = useState<HokTitleType>('MOVIE');\n const [eSynopsis, setESynopsis] = useState('');\n const [eGenres, setEGenres] = useState('');\n const [eTags, setETags] = useState('');\n const [eLanguage, setELanguage] = useState('');\n const [eCountry, setECountry] = useState('');\n const [eYear, setEYear] = useState('');\n const [eRuntime, setERuntime] = useState('');\n const [eCertification, setECertification] = useState('');\n const [eStudioId, setEStudioId] = useState('');\n const [eAiDisclosure, setEAiDisclosure] = useState(false);\n\n // ── Add-credit form state ──────────────────────────────────────────────────\n const [personSearch, setPersonSearch] = useState('');\n const [creditPersonId, setCreditPersonId] = useState('');\n const [creditRole, setCreditRole] = useState<HokCreditRole>('ACTOR');\n const [creditCharacter, setCreditCharacter] = useState('');\n const [creditBilling, setCreditBilling] = useState('');\n const people = usePeople({ limit: 50, offset: 0 }, personSearch);\n\n // ── Add-season form state ──────────────────────────────────────────────────\n const [seasonNumber, setSeasonNumber] = useState('');\n const [seasonName, setSeasonName] = useState('');\n const [seasonSynopsis, setSeasonSynopsis] = useState('');\n const [seasonAirDate, setSeasonAirDate] = useState('');\n\n // ── Add-episode form state ─────────────────────────────────────────────────\n const [episodeSeasonId, setEpisodeSeasonId] = useState('');\n const [episodeNumber, setEpisodeNumber] = useState('');\n const [episodeName, setEpisodeName] = useState('');\n const [episodeSynopsis, setEpisodeSynopsis] = useState('');\n const [episodeRuntime, setEpisodeRuntime] = useState('');\n const [episodeAirDate, setEpisodeAirDate] = useState('');\n const [episodeVideoFile, setEpisodeVideoFile] = useState<File | null>(null);\n const [episodeVideoUploading, setEpisodeVideoUploading] = useState(false);\n\n const [watchedNotice, setWatchedNotice] = useState(false);\n\n if (isLoading) {\n return (\n <PageLayout title=\"Title\">\n <LoadingState label=\"Loading title…\" />\n </PageLayout>\n );\n }\n\n if (isError || !title) {\n return (\n <PageLayout title=\"Title\">\n <ErrorState\n title=\"Title not found\"\n message=\"This title may have been archived or you may not have access.\"\n onRetry={() => void refetch()}\n />\n </PageLayout>\n );\n }\n\n const isSeries = title.type === 'SERIES';\n\n const closePanel = () => setOpenPanel('none');\n\n const openEdit = () => {\n setActionError(null);\n setETitle(title.title);\n setEType(title.type);\n setESynopsis(title.synopsis ?? '');\n setEGenres(title.genres.join(', '));\n setETags(title.tags.join(', '));\n setELanguage(title.originalLanguage ?? '');\n setECountry(title.originCountry ?? '');\n setEYear(title.releaseYear ? String(title.releaseYear) : '');\n setERuntime(title.runtimeMinutes ? String(title.runtimeMinutes) : '');\n setECertification(title.certification ?? '');\n setEStudioId(title.studioId ?? '');\n setEAiDisclosure(title.aiDisclosure);\n setOpenPanel('edit');\n };\n\n const handleTransition = async (status: HokTitleStatus) => {\n setActionError(null);\n try {\n await transition.mutateAsync({ id: title.id, status });\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Transition failed');\n }\n };\n\n const handleArchive = async () => {\n setActionError(null);\n try {\n await archive.mutateAsync(title.id);\n navigateTo('catalog/titles');\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Archive failed');\n }\n };\n\n const handleEditSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setActionError(null);\n if (!eTitle.trim()) {\n setActionError('Title is required.');\n return;\n }\n const input: UpdateTitleInput = {\n title: eTitle.trim(),\n type: eType,\n synopsis: eSynopsis.trim() || undefined,\n genres: splitCsv(eGenres),\n tags: splitCsv(eTags),\n originalLanguage: eLanguage.trim() || undefined,\n originCountry: eCountry.trim() || undefined,\n releaseYear: eYear.trim() ? Number(eYear) : undefined,\n runtimeMinutes: eRuntime.trim() ? Number(eRuntime) : undefined,\n certification: eCertification.trim() || undefined,\n studioId: eStudioId || undefined,\n aiDisclosure: eAiDisclosure,\n };\n try {\n await updateTitle.mutateAsync({ id: title.id, input });\n closePanel();\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to update title');\n }\n };\n\n const handleCreditSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setActionError(null);\n if (!creditPersonId) {\n setActionError('Select a person to credit.');\n return;\n }\n try {\n await addCredit.mutateAsync({\n personId: creditPersonId,\n titleId: title.id,\n role: creditRole,\n characterName: creditCharacter.trim() || undefined,\n billingOrder: creditBilling.trim() ? Number(creditBilling) : undefined,\n });\n setCreditPersonId('');\n setCreditCharacter('');\n setCreditBilling('');\n setPersonSearch('');\n closePanel();\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to add credit');\n }\n };\n\n const handleSeasonSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setActionError(null);\n if (!seasonNumber.trim()) {\n setActionError('Season number is required.');\n return;\n }\n try {\n await createSeason.mutateAsync({\n titleId: title.id,\n number: Number(seasonNumber),\n name: seasonName.trim() || undefined,\n synopsis: seasonSynopsis.trim() || undefined,\n airDate: dateToIso(seasonAirDate),\n });\n setSeasonNumber('');\n setSeasonName('');\n setSeasonSynopsis('');\n setSeasonAirDate('');\n closePanel();\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to add season');\n }\n };\n\n const handleEpisodeSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setActionError(null);\n if (!episodeNumber.trim()) {\n setActionError('Episode number is required.');\n return;\n }\n if (!episodeName.trim()) {\n setActionError('Episode name is required.');\n return;\n }\n try {\n // Video is optional and, unlike title-level media, can only be attached\n // at creation time (there is no hokUpdateEpisode yet) -- so we upload it\n // to wspace-files-svc first and pass the resulting id straight through.\n let fileId: string | undefined;\n if (episodeVideoFile) {\n setEpisodeVideoUploading(true);\n try {\n const uploaded = await uploadFileToFiles(episodeVideoFile, FILE_FOLDERS.episodes);\n fileId = uploaded.id;\n } finally {\n setEpisodeVideoUploading(false);\n }\n }\n await createEpisode.mutateAsync({\n titleId: title.id,\n number: Number(episodeNumber),\n name: episodeName.trim(),\n seasonId: episodeSeasonId || undefined,\n synopsis: episodeSynopsis.trim() || undefined,\n runtimeMinutes: episodeRuntime.trim() ? Number(episodeRuntime) : undefined,\n airDate: dateToIso(episodeAirDate),\n fileId,\n });\n setEpisodeSeasonId('');\n setEpisodeNumber('');\n setEpisodeName('');\n setEpisodeSynopsis('');\n setEpisodeRuntime('');\n setEpisodeAirDate('');\n setEpisodeVideoFile(null);\n closePanel();\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to add episode');\n }\n };\n\n const handleMarkWatched = async () => {\n setActionError(null);\n setWatchedNotice(false);\n if (!entitlement.data?.entitled) {\n setActionError('You are not entitled to watch this title.');\n return;\n }\n try {\n await recordProgress.mutateAsync({\n titleId: title.id,\n positionSeconds: (title.runtimeMinutes ?? 0) * 60,\n completed: true,\n lastDevice: 'web',\n });\n setWatchedNotice(true);\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to record progress');\n }\n };\n\n const handleClipSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setClipError(null);\n if (!clipFile) {\n setClipError('Select a clip video to upload.');\n return;\n }\n setClipUploading(true);\n try {\n const uploaded = await uploadFileToFiles(clipFile, FILE_FOLDERS.clips);\n await createClip.mutateAsync({\n titleId: title.id,\n videoFileId: uploaded.id,\n caption: clipCaption.trim() || undefined,\n durationSeconds: clipDuration.trim() ? Number(clipDuration) : undefined,\n language: clipLanguage.trim() || undefined,\n });\n setClipFile(null);\n setClipCaption('');\n setClipDuration('');\n setClipLanguage('');\n if (clipInputRef.current) clipInputRef.current.value = '';\n setShowClipForm(false);\n setClipPage(0);\n } catch (err) {\n setClipError(err instanceof Error ? err.message : 'Failed to add clip');\n } finally {\n setClipUploading(false);\n }\n };\n\n const handleClipDelete = async (clip: HokClip) => {\n setActionError(null);\n setDeletingClipId(clip.id);\n try {\n await deleteClip.mutateAsync({ id: clip.id, titleId: title.id });\n } catch (err) {\n setActionError(err instanceof Error ? err.message : 'Failed to delete clip');\n } finally {\n setDeletingClipId(null);\n }\n };\n\n const reviewItems = reviews.data?.items ?? [];\n const clipItems = clips.data?.items ?? [];\n const avgScore =\n reviewItems.length > 0\n ? reviewItems.reduce((sum, r) => sum + r.score, 0) / reviewItems.length\n : null;\n\n const facts: Array<{ icon: typeof Calendar; label: string; value: string }> = [];\n if (title.releaseDate)\n facts.push({ icon: Calendar, label: 'Release', value: formatDate(title.releaseDate) });\n else if (title.releaseYear)\n facts.push({ icon: Calendar, label: 'Year', value: String(title.releaseYear) });\n if (title.runtimeMinutes)\n facts.push({ icon: Clock, label: 'Runtime', value: `${title.runtimeMinutes} min` });\n if (title.originalLanguage)\n facts.push({ icon: Languages, label: 'Language', value: title.originalLanguage });\n if (title.originCountry)\n facts.push({ icon: Globe, label: 'Country', value: title.originCountry });\n if (title.certification)\n facts.push({ icon: ShieldCheck, label: 'Certification', value: title.certification });\n\n const peopleItems = people.data?.items ?? [];\n\n return (\n <PageLayout\n title={\n <span className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigateTo('catalog/titles')}\n className=\"rounded-md p-1 text-text-secondary hover:text-text-primary\"\n aria-label=\"Back to catalog\"\n >\n <ArrowLeft className=\"h-5 w-5\" />\n </button>\n {title.title}\n </span>\n }\n description={`${formatEnumLabel(title.type)}${title.studio ? ` · ${title.studio.name}` : ''}`}\n actions={\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={openEdit}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-seam px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Pencil className=\"h-3.5 w-3.5\" />\n Edit\n </button>\n <StatusBadge status={title.status} />\n </div>\n }\n >\n {actionError && (\n <div className=\"mb-4 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text\">\n {actionError}\n </div>\n )}\n\n {/* Cinematic backdrop / poster header (art + synopsis + quick facts) */}\n <TitleHero title={title} />\n\n {/* Edit-title panel (full-width; reuses the create-form field set) */}\n {openPanel === 'edit' && (\n <GlassCard treatment=\"metric\" className=\"mb-6 border-border-seam p-5\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-sm font-semibold text-text-primary\">Edit title</h2>\n <button\n type=\"button\"\n onClick={closePanel}\n className=\"rounded-md p-1 text-text-secondary hover:text-text-primary\"\n aria-label=\"Close edit form\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n <form onSubmit={handleEditSubmit} className=\"space-y-5\">\n <div>\n <label htmlFor=\"edit-title\" className={labelClass}>\n Title *\n </label>\n <input\n id=\"edit-title\"\n type=\"text\"\n value={eTitle}\n onChange={(e) => setETitle(e.target.value)}\n className={fieldClass}\n required\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"edit-type\" className={labelClass}>\n Type\n </label>\n <select\n id=\"edit-type\"\n value={eType}\n onChange={(e) => setEType(e.target.value as HokTitleType)}\n className={fieldClass}\n >\n {TYPE_OPTIONS.map((t) => (\n <option key={t} value={t}>\n {formatEnumLabel(t)}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"edit-studio\" className={labelClass}>\n Studio\n </label>\n <select\n id=\"edit-studio\"\n value={eStudioId}\n onChange={(e) => setEStudioId(e.target.value)}\n className={fieldClass}\n >\n <option value=\"\">No studio</option>\n {(studios.data?.items ?? []).map((s) => (\n <option key={s.id} value={s.id}>\n {s.name}\n </option>\n ))}\n </select>\n </div>\n </div>\n\n <div>\n <label htmlFor=\"edit-synopsis\" className={labelClass}>\n Synopsis\n </label>\n <textarea\n id=\"edit-synopsis\"\n value={eSynopsis}\n onChange={(e) => setESynopsis(e.target.value)}\n rows={4}\n className={fieldClass}\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"edit-genres\" className={labelClass}>\n Genres (comma-separated)\n </label>\n <input\n id=\"edit-genres\"\n type=\"text\"\n value={eGenres}\n onChange={(e) => setEGenres(e.target.value)}\n placeholder=\"Drama, Thriller\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"edit-tags\" className={labelClass}>\n Tags (comma-separated)\n </label>\n <input\n id=\"edit-tags\"\n type=\"text\"\n value={eTags}\n onChange={(e) => setETags(e.target.value)}\n placeholder=\"award-winner, indie\"\n className={fieldClass}\n />\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-3\">\n <div>\n <label htmlFor=\"edit-language\" className={labelClass}>\n Original Language\n </label>\n <input\n id=\"edit-language\"\n type=\"text\"\n value={eLanguage}\n onChange={(e) => setELanguage(e.target.value)}\n placeholder=\"en\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"edit-country\" className={labelClass}>\n Origin Country\n </label>\n <input\n id=\"edit-country\"\n type=\"text\"\n value={eCountry}\n onChange={(e) => setECountry(e.target.value)}\n placeholder=\"US\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"edit-certification\" className={labelClass}>\n Certification\n </label>\n <input\n id=\"edit-certification\"\n type=\"text\"\n value={eCertification}\n onChange={(e) => setECertification(e.target.value)}\n placeholder=\"PG-13\"\n className={fieldClass}\n />\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"edit-year\" className={labelClass}>\n Release Year\n </label>\n <input\n id=\"edit-year\"\n type=\"number\"\n value={eYear}\n onChange={(e) => setEYear(e.target.value)}\n placeholder=\"2026\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"edit-runtime\" className={labelClass}>\n Runtime (minutes)\n </label>\n <input\n id=\"edit-runtime\"\n type=\"number\"\n value={eRuntime}\n onChange={(e) => setERuntime(e.target.value)}\n placeholder=\"120\"\n className={fieldClass}\n />\n </div>\n </div>\n\n <label className=\"flex items-center gap-2 text-sm text-text-primary\">\n <input\n type=\"checkbox\"\n checked={eAiDisclosure}\n onChange={(e) => setEAiDisclosure(e.target.checked)}\n className=\"h-4 w-4 rounded border-border-subtle\"\n />\n This title contains AI-generated or AI-altered content\n </label>\n\n <div className=\"flex items-center gap-3 pt-1\">\n <button\n type=\"submit\"\n disabled={updateTitle.isPending}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n {updateTitle.isPending ? 'Saving…' : 'Save changes'}\n </button>\n <button\n type=\"button\"\n onClick={closePanel}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n </GlassCard>\n )}\n\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Main column */}\n <div className=\"space-y-6 lg:col-span-2\">\n {/* Artwork & Media */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <PanelHeader icon={ImageIcon} title=\"Artwork & Media\" />\n <p className=\"-mt-2 mb-4 text-xs text-text-secondary\">\n Poster and backdrop art, plus the trailer and full-length video master. Files are\n stored in the workspace files service; the title keeps only a reference.\n </p>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n {MEDIA_SLOTS.map((slot) => (\n <MediaSlot\n key={slot.field}\n titleId={title.id}\n config={slot}\n currentFileId={title[slot.field]}\n />\n ))}\n </div>\n </GlassCard>\n\n {/* Credits */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <PanelHeader\n icon={Users}\n title=\"Cast & Crew\"\n count={title.credits.length}\n actions={\n <button\n type=\"button\"\n onClick={() => {\n setActionError(null);\n setOpenPanel(openPanel === 'credit' ? 'none' : 'credit');\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-2.5 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <UserPlus className=\"h-3.5 w-3.5\" />\n Add credit\n </button>\n }\n />\n\n {openPanel === 'credit' && (\n <form\n onSubmit={handleCreditSubmit}\n className=\"mb-4 space-y-4 rounded-lg border border-border-seam bg-bg-surface p-4\"\n >\n <div>\n <label htmlFor=\"credit-search\" className={labelClass}>\n Search people\n </label>\n <input\n id=\"credit-search\"\n type=\"text\"\n value={personSearch}\n onChange={(e) => setPersonSearch(e.target.value)}\n placeholder=\"Type a name to filter…\"\n className={fieldClass}\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"credit-person\" className={labelClass}>\n Person *\n </label>\n <select\n id=\"credit-person\"\n value={creditPersonId}\n onChange={(e) => setCreditPersonId(e.target.value)}\n className={fieldClass}\n required\n >\n <option value=\"\">\n {people.isLoading\n ? 'Loading people…'\n : peopleItems.length === 0\n ? 'No people found'\n : 'Select a person'}\n </option>\n {peopleItems.map((p) => (\n <option key={p.id} value={p.id}>\n {p.name}\n {p.knownFor ? ` — ${p.knownFor}` : ''}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"credit-role\" className={labelClass}>\n Role\n </label>\n <select\n id=\"credit-role\"\n value={creditRole}\n onChange={(e) => setCreditRole(e.target.value as HokCreditRole)}\n className={fieldClass}\n >\n {CREDIT_ROLE_OPTIONS.map((r) => (\n <option key={r} value={r}>\n {formatEnumLabel(r)}\n </option>\n ))}\n </select>\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"credit-character\" className={labelClass}>\n Character name\n </label>\n <input\n id=\"credit-character\"\n type=\"text\"\n value={creditCharacter}\n onChange={(e) => setCreditCharacter(e.target.value)}\n placeholder=\"e.g. Captain Rao\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"credit-billing\" className={labelClass}>\n Billing order\n </label>\n <input\n id=\"credit-billing\"\n type=\"number\"\n value={creditBilling}\n onChange={(e) => setCreditBilling(e.target.value)}\n placeholder=\"1\"\n className={fieldClass}\n />\n </div>\n </div>\n <div className=\"flex items-center gap-3\">\n <button\n type=\"submit\"\n disabled={addCredit.isPending}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n <Plus className=\"h-4 w-4\" />\n {addCredit.isPending ? 'Adding…' : 'Add credit'}\n </button>\n <button\n type=\"button\"\n onClick={closePanel}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n )}\n\n {title.credits.length === 0 ? (\n <EmptyState\n title=\"No credits recorded yet\"\n description=\"Add the cast and crew who worked on this title.\"\n />\n ) : (\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4\">\n {[...title.credits]\n .sort((a, b) => a.billingOrder - b.billingOrder)\n .map((credit) => (\n <CreditTile key={credit.id} credit={credit} />\n ))}\n <button\n type=\"button\"\n onClick={() => {\n setActionError(null);\n setOpenPanel(openPanel === 'credit' ? 'none' : 'credit');\n }}\n className=\"flex min-h-[9.5rem] flex-col items-center justify-center gap-2 rounded-xl border border-dashed border-border-seam bg-bg-surface p-3 text-text-secondary transition-colors hover:border-border-strong hover:text-text-primary\"\n >\n <span className=\"flex h-10 w-10 items-center justify-center rounded-full bg-bg-sunken\">\n <UserPlus className=\"h-5 w-5\" />\n </span>\n <span className=\"text-xs font-medium\">Add credit</span>\n </button>\n </div>\n )}\n </GlassCard>\n\n {/* Seasons & episodes */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <PanelHeader\n icon={Layers}\n title=\"Episodes\"\n count={title.episodes.length}\n actions={\n isSeries ? (\n <>\n <button\n type=\"button\"\n onClick={() => {\n setActionError(null);\n setOpenPanel(openPanel === 'season' ? 'none' : 'season');\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-2.5 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n Add season\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setActionError(null);\n setOpenPanel(openPanel === 'episode' ? 'none' : 'episode');\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-2.5 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n Add episode\n </button>\n </>\n ) : undefined\n }\n />\n\n {isSeries && openPanel === 'season' && (\n <form\n onSubmit={handleSeasonSubmit}\n className=\"mb-4 space-y-4 rounded-lg border border-border-seam bg-bg-surface p-4\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"season-number\" className={labelClass}>\n Season number *\n </label>\n <input\n id=\"season-number\"\n type=\"number\"\n value={seasonNumber}\n onChange={(e) => setSeasonNumber(e.target.value)}\n placeholder=\"1\"\n className={fieldClass}\n required\n />\n </div>\n <div>\n <label htmlFor=\"season-name\" className={labelClass}>\n Name\n </label>\n <input\n id=\"season-name\"\n type=\"text\"\n value={seasonName}\n onChange={(e) => setSeasonName(e.target.value)}\n placeholder=\"Season 1\"\n className={fieldClass}\n />\n </div>\n </div>\n <div>\n <label htmlFor=\"season-synopsis\" className={labelClass}>\n Synopsis\n </label>\n <textarea\n id=\"season-synopsis\"\n value={seasonSynopsis}\n onChange={(e) => setSeasonSynopsis(e.target.value)}\n rows={3}\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"season-airdate\" className={labelClass}>\n Air date\n </label>\n <input\n id=\"season-airdate\"\n type=\"date\"\n value={seasonAirDate}\n onChange={(e) => setSeasonAirDate(e.target.value)}\n className={fieldClass}\n />\n </div>\n <div className=\"flex items-center gap-3\">\n <button\n type=\"submit\"\n disabled={createSeason.isPending}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n <Plus className=\"h-4 w-4\" />\n {createSeason.isPending ? 'Adding…' : 'Add season'}\n </button>\n <button\n type=\"button\"\n onClick={closePanel}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n )}\n\n {isSeries && openPanel === 'episode' && (\n <form\n onSubmit={handleEpisodeSubmit}\n className=\"mb-4 space-y-4 rounded-lg border border-border-seam bg-bg-surface p-4\"\n >\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"episode-season\" className={labelClass}>\n Season\n </label>\n <select\n id=\"episode-season\"\n value={episodeSeasonId}\n onChange={(e) => setEpisodeSeasonId(e.target.value)}\n className={fieldClass}\n >\n <option value=\"\">No season</option>\n {[...title.seasons]\n .sort((a, b) => a.number - b.number)\n .map((s) => (\n <option key={s.id} value={s.id}>\n {s.name ? `${s.number}. ${s.name}` : `Season ${s.number}`}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"episode-number\" className={labelClass}>\n Episode number *\n </label>\n <input\n id=\"episode-number\"\n type=\"number\"\n value={episodeNumber}\n onChange={(e) => setEpisodeNumber(e.target.value)}\n placeholder=\"1\"\n className={fieldClass}\n required\n />\n </div>\n </div>\n <div>\n <label htmlFor=\"episode-name\" className={labelClass}>\n Name *\n </label>\n <input\n id=\"episode-name\"\n type=\"text\"\n value={episodeName}\n onChange={(e) => setEpisodeName(e.target.value)}\n placeholder=\"Pilot\"\n className={fieldClass}\n required\n />\n </div>\n <div>\n <label htmlFor=\"episode-synopsis\" className={labelClass}>\n Synopsis\n </label>\n <textarea\n id=\"episode-synopsis\"\n value={episodeSynopsis}\n onChange={(e) => setEpisodeSynopsis(e.target.value)}\n rows={3}\n className={fieldClass}\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"episode-runtime\" className={labelClass}>\n Runtime (minutes)\n </label>\n <input\n id=\"episode-runtime\"\n type=\"number\"\n value={episodeRuntime}\n onChange={(e) => setEpisodeRuntime(e.target.value)}\n placeholder=\"45\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"episode-airdate\" className={labelClass}>\n Air date\n </label>\n <input\n id=\"episode-airdate\"\n type=\"date\"\n value={episodeAirDate}\n onChange={(e) => setEpisodeAirDate(e.target.value)}\n className={fieldClass}\n />\n </div>\n </div>\n <div>\n <label htmlFor=\"episode-video\" className={labelClass}>\n Video (optional)\n </label>\n <input\n id=\"episode-video\"\n type=\"file\"\n accept=\"video/*\"\n onChange={(e) => setEpisodeVideoFile(e.target.files?.[0] ?? null)}\n className={fieldClass}\n />\n <p className=\"mt-1 text-xs text-text-secondary\">\n Uploaded to the workspace files service and attached on creation -- there is no\n way to attach or replace a video on an existing episode yet.\n </p>\n </div>\n <div className=\"flex items-center gap-3\">\n <button\n type=\"submit\"\n disabled={createEpisode.isPending || episodeVideoUploading}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n <Plus className=\"h-4 w-4\" />\n {episodeVideoUploading\n ? 'Uploading video…'\n : createEpisode.isPending\n ? 'Adding…'\n : 'Add episode'}\n </button>\n <button\n type=\"button\"\n onClick={closePanel}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n )}\n\n {title.episodes.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {isSeries\n ? 'No episodes yet. Add a season, then episodes, to build out this series.'\n : 'No episodes recorded for this title.'}\n </p>\n ) : (\n <ul className=\"space-y-1\">\n {[...title.episodes]\n .sort((a, b) => a.number - b.number)\n .map((ep) => (\n <li\n key={ep.id}\n className=\"flex items-center gap-3 rounded-lg px-2 py-2 transition-colors hover:bg-bg-sunken\"\n >\n <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-bg-sunken text-xs font-semibold text-text-secondary\">\n {ep.number}\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"truncate text-sm font-medium text-text-primary\">{ep.name}</p>\n {ep.synopsis && (\n <p className=\"line-clamp-1 text-xs text-text-secondary\">{ep.synopsis}</p>\n )}\n </div>\n {ep.runtimeMinutes && (\n <span className=\"shrink-0 text-xs text-text-secondary\">\n {ep.runtimeMinutes} min\n </span>\n )}\n </li>\n ))}\n </ul>\n )}\n </GlassCard>\n\n {/* Reviews */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <PanelHeader icon={Star} title=\"Reviews\" count={reviewItems.length} />\n {reviewItems.length === 0 ? (\n <EmptyState\n title=\"No reviews yet\"\n description=\"Reviews from verified viewers will appear here.\"\n />\n ) : (\n <>\n {avgScore !== null && (\n <div className=\"mb-4 flex items-center gap-4 rounded-xl border border-border-seam bg-bg-surface p-4\">\n <div className=\"flex flex-col items-center\">\n <span className=\"text-3xl font-semibold leading-none text-text-primary\">\n {avgScore.toFixed(1)}\n </span>\n <span className=\"mt-1 text-[10px] uppercase tracking-wide text-text-secondary\">\n / 10\n </span>\n </div>\n <div className=\"min-w-0\">\n <RatingDisplay value={avgScore / 2} count={reviewItems.length} size=\"md\" />\n <p className=\"mt-1 text-xs text-text-secondary\">\n Average across {reviewItems.length}{' '}\n {reviewItems.length === 1 ? 'review' : 'reviews'}\n </p>\n </div>\n </div>\n )}\n <ul className=\"space-y-3\">\n {reviewItems.map((review) => (\n <li\n key={review.id}\n className=\"rounded-lg border border-border-seam bg-bg-surface p-3\"\n >\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-semibold text-text-primary\">\n {review.score}/10\n </span>\n <div className=\"flex items-center gap-2\">\n {review.verifiedWatch && (\n <span className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[10px] text-status-success-text\">\n Verified\n </span>\n )}\n <StatusBadge status={review.status} />\n </div>\n </div>\n {review.body && (\n <p className=\"mt-1 text-sm text-text-secondary\">{review.body}</p>\n )}\n </li>\n ))}\n </ul>\n </>\n )}\n </GlassCard>\n\n {/* Clips */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <PanelHeader\n icon={Video}\n title=\"Clips\"\n count={clips.data?.totalCount ?? clipItems.length}\n actions={\n <button\n type=\"button\"\n onClick={() => {\n setClipError(null);\n setShowClipForm((v) => !v);\n }}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-2.5 py-1 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n Add clip\n </button>\n }\n />\n\n {showClipForm && (\n <form\n onSubmit={handleClipSubmit}\n className=\"mb-4 space-y-4 rounded-lg border border-border-seam bg-bg-surface p-4\"\n >\n <div>\n <label htmlFor=\"clip-file\" className={labelClass}>\n Clip video * (short vertical MP4)\n </label>\n <input\n id=\"clip-file\"\n ref={clipInputRef}\n type=\"file\"\n accept=\"video/*\"\n onChange={(e) => setClipFile(e.target.files?.[0] ?? null)}\n className={fieldClass}\n />\n {clipFile && (\n <p className=\"mt-1 truncate text-xs text-text-secondary\">\n Selected: {clipFile.name}\n </p>\n )}\n </div>\n <div>\n <label htmlFor=\"clip-caption\" className={labelClass}>\n Caption\n </label>\n <input\n id=\"clip-caption\"\n type=\"text\"\n value={clipCaption}\n onChange={(e) => setClipCaption(e.target.value)}\n placeholder=\"e.g. Official teaser\"\n className={fieldClass}\n />\n </div>\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"clip-duration\" className={labelClass}>\n Duration (seconds)\n </label>\n <input\n id=\"clip-duration\"\n type=\"number\"\n min={0}\n value={clipDuration}\n onChange={(e) => setClipDuration(e.target.value)}\n placeholder=\"30\"\n className={fieldClass}\n />\n </div>\n <div>\n <label htmlFor=\"clip-language\" className={labelClass}>\n Language\n </label>\n <input\n id=\"clip-language\"\n type=\"text\"\n value={clipLanguage}\n onChange={(e) => setClipLanguage(e.target.value)}\n placeholder=\"en\"\n className={fieldClass}\n />\n </div>\n </div>\n {clipError && <p className=\"text-xs text-status-error-text\">{clipError}</p>}\n <div className=\"flex items-center gap-3\">\n <button\n type=\"submit\"\n disabled={clipUploading}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text transition-opacity hover:opacity-90 disabled:opacity-50\"\n >\n <Upload className=\"h-4 w-4\" />\n {clipUploading ? 'Uploading…' : 'Add clip'}\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setShowClipForm(false);\n setClipError(null);\n }}\n className=\"rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n </div>\n </form>\n )}\n\n {clips.isLoading ? (\n <LoadingState label=\"Loading clips…\" className=\"min-h-[20vh]\" />\n ) : clips.isError ? (\n <ErrorState\n title=\"Could not load clips\"\n message=\"Something went wrong fetching this title's clips.\"\n onRetry={() => void clips.refetch()}\n className=\"min-h-[20vh]\"\n />\n ) : clipItems.length === 0 ? (\n <EmptyState\n title=\"No clips yet\"\n description=\"Upload a short vertical clip to promote this title.\"\n />\n ) : (\n <>\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4\">\n {clipItems.map((clip) => (\n <ClipCard\n key={clip.id}\n clip={clip}\n deleting={deletingClipId === clip.id}\n onDelete={(c) => void handleClipDelete(c)}\n />\n ))}\n </div>\n <Pagination\n page={clipPage}\n hasMore={clips.data?.pageInfo.hasMore ?? false}\n shownCount={clipItems.length}\n onPageChange={setClipPage}\n />\n </>\n )}\n </GlassCard>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Watch / entitlement */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Play className=\"h-4 w-4\" />\n Watch\n </h2>\n {entitlement.isLoading ? (\n <p className=\"text-sm text-text-secondary\">Checking access…</p>\n ) : entitlement.isError ? (\n <div className=\"space-y-2\">\n <p className=\"text-sm text-status-error-text\">Could not check entitlement.</p>\n <button\n type=\"button\"\n onClick={() => void entitlement.refetch()}\n className=\"rounded-lg border border-border-seam px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Retry\n </button>\n </div>\n ) : entitlement.data?.entitled ? (\n <div className=\"space-y-3\">\n {entitlement.data.modes.length > 0 && (\n <div className=\"flex flex-wrap gap-1.5\">\n {entitlement.data.modes.map((mode) => (\n <span\n key={mode}\n className=\"rounded-full bg-status-success-bg-subtle px-2.5 py-0.5 text-xs text-status-success-text\"\n >\n {formatEnumLabel(mode)}\n </span>\n ))}\n </div>\n )}\n {watchedNotice ? (\n <p className=\"flex items-center gap-2 text-sm text-status-success-text\">\n <CheckCircle2 className=\"h-4 w-4\" />\n Marked as watched — see Continue Watching.\n </p>\n ) : (\n <button\n type=\"button\"\n disabled={recordProgress.isPending}\n onClick={() => void handleMarkWatched()}\n className=\"inline-flex w-full items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n <Play className=\"h-4 w-4\" />\n {recordProgress.isPending ? 'Saving…' : 'Mark as watched'}\n </button>\n )}\n </div>\n ) : (\n <div className=\"flex items-start gap-2 rounded-lg border border-border-seam bg-bg-sunken px-3 py-2.5\">\n <Lock className=\"mt-0.5 h-4 w-4 shrink-0 text-text-secondary\" />\n <p className=\"text-sm text-text-secondary\">\n You are not entitled to watch this title. Grant an entitlement or add a rights\n window to enable playback.\n </p>\n </div>\n )}\n </GlassCard>\n\n {/* Lifecycle actions */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-3 text-sm font-semibold text-text-primary\">Publication</h2>\n <div className=\"flex flex-wrap gap-2\">\n {NEXT_STATUSES[title.status].map((status) => (\n <button\n key={status}\n type=\"button\"\n disabled={transition.isPending}\n onClick={() => void handleTransition(status)}\n className=\"rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50 transition-opacity\"\n >\n {formatEnumLabel(status)}\n </button>\n ))}\n {NEXT_STATUSES[title.status].length === 0 && (\n <p className=\"text-xs text-text-secondary\">No further transitions available.</p>\n )}\n </div>\n {title.status !== 'ARCHIVED' && (\n <button\n type=\"button\"\n disabled={archive.isPending}\n onClick={() => void handleArchive()}\n className=\"mt-3 inline-flex items-center gap-2 rounded-lg border border-status-error-border px-3 py-1.5 text-xs font-medium text-status-error-text hover:bg-status-error-bg-subtle disabled:opacity-50 transition-colors\"\n >\n <Archive className=\"h-3.5 w-3.5\" />\n Archive Title\n </button>\n )}\n </GlassCard>\n\n {/* Facts */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-3 text-sm font-semibold text-text-primary\">Details</h2>\n <dl className=\"space-y-2\">\n {facts.map((fact) => {\n const Icon = fact.icon;\n return (\n <div key={fact.label} className=\"flex items-center justify-between text-sm\">\n <dt className=\"flex items-center gap-2 text-text-secondary\">\n <Icon className=\"h-3.5 w-3.5\" />\n {fact.label}\n </dt>\n <dd className=\"font-medium text-text-primary\">{fact.value}</dd>\n </div>\n );\n })}\n {title.aiDisclosure && (\n <div className=\"flex items-center gap-2 pt-1 text-sm text-text-secondary\">\n <Sparkles className=\"h-3.5 w-3.5\" />\n Contains AI-generated content\n </div>\n )}\n </dl>\n </GlassCard>\n\n {/* Genres & tags */}\n {(title.genres.length > 0 || title.tags.length > 0) && (\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n {title.genres.length > 0 && (\n <>\n <h3 className=\"mb-2 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n Genres\n </h3>\n <div className=\"mb-3 flex flex-wrap gap-1.5\">\n {title.genres.map((g) => (\n <span\n key={g}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-primary\"\n >\n {g}\n </span>\n ))}\n </div>\n </>\n )}\n {title.tags.length > 0 && (\n <>\n <h3 className=\"mb-2 text-xs font-semibold uppercase tracking-wide text-text-secondary\">\n Tags\n </h3>\n <div className=\"flex flex-wrap gap-1.5\">\n {title.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n </>\n )}\n </GlassCard>\n )}\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlayerPage.d.ts","sourceRoot":"","sources":["../../../../src/hookmovies/pages/consumer/PlayerPage.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"PlayerPage.d.ts","sourceRoot":"","sources":["../../../../src/hookmovies/pages/consumer/PlayerPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAqD,MAAM,OAAO,CAAC;AA8FnF,eAAO,MAAM,UAAU,EAAE,EAyoBxB,CAAC"}
|
|
@@ -30,7 +30,7 @@ var _ = 5, ye = .1, be = 1e4, xe = 15, Se = ({ localization: e }) => {
|
|
|
30
30
|
default: e.isDefault
|
|
31
31
|
});
|
|
32
32
|
}, v = () => {
|
|
33
|
-
let { titleId: f, episodeId: p } = ge(), { navigateTo: g } = e(), { data: v, isLoading: we, isError: Te, refetch: Ee } = a(f), S = t(f), C = n(f, p), w = r(f), De = i(), T = l(() => p ? v?.episodes.find((e) => e.id === p) ?? null : null, [p, v]), E = p ? void 0 : v?.videoFileId ?? void 0, D = o(E), O = o(v?.posterFileId ?? void 0), Oe = o(v?.backdropFileId ?? void 0), k = l(() => (C.data ?? []).filter((e) => e.kind === "SUBTITLE" || e.kind === "CAPTION"), [C.data]), ke = l(() => (C.data ?? []).filter((e) => e.kind === "DUB"), [C.data]), A = u(null), Ae = u(null), [j, M] = d(!1), [N, P] = d(0), [F, je] = d(0), [I, Me] = d(1), [L, Ne] = d(!1), [Pe, R] = d(!1), [z, Fe] = d(!1), [B, V] = d(!1), [Ie, Le] = d(!1), [Re, ze] = d(!0), [H, Be] = d("none"), [U, Ve] = d(-1), He = u(0), Ue = u(!1), We = u(!1), W = u(null), Ge = u(De.mutate);
|
|
33
|
+
let { titleId: f, episodeId: p } = ge(), { navigateTo: g } = e(), { data: v, isLoading: we, isError: Te, refetch: Ee } = a(f), S = t(f), C = n(f, p), w = r(f), De = i(), T = l(() => p ? v?.episodes.find((e) => e.id === p) ?? null : null, [p, v]), E = p ? T?.fileId ?? void 0 : v?.videoFileId ?? void 0, D = o(E), O = o(v?.posterFileId ?? void 0), Oe = o(v?.backdropFileId ?? void 0), k = l(() => (C.data ?? []).filter((e) => e.kind === "SUBTITLE" || e.kind === "CAPTION"), [C.data]), ke = l(() => (C.data ?? []).filter((e) => e.kind === "DUB"), [C.data]), A = u(null), Ae = u(null), [j, M] = d(!1), [N, P] = d(0), [F, je] = d(0), [I, Me] = d(1), [L, Ne] = d(!1), [Pe, R] = d(!1), [z, Fe] = d(!1), [B, V] = d(!1), [Ie, Le] = d(!1), [Re, ze] = d(!0), [H, Be] = d("none"), [U, Ve] = d(-1), He = u(0), Ue = u(!1), We = u(!1), W = u(null), Ge = u(De.mutate);
|
|
34
34
|
Ge.current = De.mutate;
|
|
35
35
|
let Ke = u(j);
|
|
36
36
|
Ke.current = j;
|