@burdenoff/microfe-hookmovies 2026.705.2 → 2026.706.1

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.
@@ -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\nimport { type FC, 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} 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 { RatingDisplay } from '../../components/RatingDisplay';\nimport { useHookMovies } from '../../context/HookMoviesContext';\nimport {\n useTitle,\n useTransitionTitle,\n useArchiveTitle,\n useReviews,\n type HokTitleStatus,\n} from '../../hooks/useHookMoviesApi';\nimport { formatDate, formatEnumLabel } from '../../utils/formatters';\n\nconst NEXT_STATUSES: Record<HokTitleStatus, HokTitleStatus[]> = {\n DRAFT: ['IN_REVIEW', 'SCHEDULED', 'PUBLISHED'],\n IN_REVIEW: ['DRAFT', 'SCHEDULED', 'PUBLISHED'],\n SCHEDULED: ['PUBLISHED', 'DRAFT'],\n PUBLISHED: ['UNPUBLISHED'],\n UNPUBLISHED: ['PUBLISHED', 'ARCHIVED'],\n ARCHIVED: [],\n};\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 [actionError, setActionError] = useState<string | null>(null);\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 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 reviewItems = reviews.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 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={<StatusBadge status={title.status} />}\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 <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 {title.synopsis && (\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-2 text-sm font-semibold text-text-primary\">Synopsis</h2>\n <p className=\"text-sm leading-relaxed text-text-secondary\">{title.synopsis}</p>\n </GlassCard>\n )}\n\n {/* Credits */}\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 <Users className=\"h-4 w-4\" />\n Cast & Crew ({title.credits.length})\n </h2>\n {title.credits.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">No credits recorded yet.</p>\n ) : (\n <ul className=\"divide-y divide-border-seam\">\n {[...title.credits]\n .sort((a, b) => a.billingOrder - b.billingOrder)\n .map((credit) => (\n <li key={credit.id} className=\"flex items-center justify-between py-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {credit.person?.name ?? 'Unknown person'}\n </p>\n {credit.characterName && (\n <p className=\"text-xs text-text-secondary\">as {credit.characterName}</p>\n )}\n </div>\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\">\n {formatEnumLabel(credit.role)}\n </span>\n </li>\n ))}\n </ul>\n )}\n </GlassCard>\n\n {/* Seasons & episodes */}\n {(title.seasons.length > 0 || title.episodes.length > 0) && (\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 <Layers className=\"h-4 w-4\" />\n Episodes ({title.episodes.length})\n </h2>\n <ul className=\"divide-y divide-border-seam\">\n {[...title.episodes]\n .sort((a, b) => a.number - b.number)\n .map((ep) => (\n <li key={ep.id} className=\"flex items-center justify-between py-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {ep.number}. {ep.name}\n </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=\"text-xs text-text-secondary\">{ep.runtimeMinutes} min</span>\n )}\n </li>\n ))}\n </ul>\n </GlassCard>\n )}\n\n {/* Reviews */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <div className=\"mb-3 flex items-center justify-between\">\n <h2 className=\"flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Star className=\"h-4 w-4\" />\n Reviews ({reviewItems.length})\n </h2>\n {avgScore !== null && (\n <RatingDisplay value={avgScore / 2} count={reviewItems.length} />\n )}\n </div>\n {reviewItems.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">No reviews yet.</p>\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 </GlassCard>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\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, 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} 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 { 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 usePeople,\n useStudios,\n type HokTitleStatus,\n type HokTitleType,\n type HokCreditRole,\n type UpdateTitleInput,\n} from '../../hooks/useHookMoviesApi';\nimport { formatDate, formatEnumLabel } from '../../utils/formatters';\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\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 const [actionError, setActionError] = useState<string | null>(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 reviewItems = reviews.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 {/* 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 {title.synopsis && (\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-2 text-sm font-semibold text-text-primary\">Synopsis</h2>\n <p className=\"text-sm leading-relaxed text-text-secondary\">{title.synopsis}</p>\n </GlassCard>\n )}\n\n {/* Credits */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <div className=\"mb-3 flex items-center justify-between gap-3\">\n <h2 className=\"flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Users className=\"h-4 w-4\" />\n Cast &amp; Crew ({title.credits.length})\n </h2>\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 </div>\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 <p className=\"text-sm text-text-secondary\">No credits recorded yet.</p>\n ) : (\n <ul className=\"divide-y divide-border-seam\">\n {[...title.credits]\n .sort((a, b) => a.billingOrder - b.billingOrder)\n .map((credit) => (\n <li key={credit.id} className=\"flex items-center justify-between py-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {credit.person?.name ?? 'Unknown person'}\n </p>\n {credit.characterName && (\n <p className=\"text-xs text-text-secondary\">as {credit.characterName}</p>\n )}\n </div>\n <span className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\">\n {formatEnumLabel(credit.role)}\n </span>\n </li>\n ))}\n </ul>\n )}\n </GlassCard>\n\n {/* Seasons & episodes */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <div className=\"mb-3 flex flex-wrap items-center justify-between gap-3\">\n <h2 className=\"flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Layers className=\"h-4 w-4\" />\n Episodes ({title.episodes.length})\n </h2>\n {isSeries && (\n <div className=\"flex items-center gap-2\">\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 </div>\n )}\n </div>\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=\"divide-y divide-border-seam\">\n {[...title.episodes]\n .sort((a, b) => a.number - b.number)\n .map((ep) => (\n <li key={ep.id} className=\"flex items-center justify-between py-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n {ep.number}. {ep.name}\n </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=\"text-xs text-text-secondary\">{ep.runtimeMinutes} min</span>\n )}\n </li>\n ))}\n </ul>\n )}\n </GlassCard>\n\n {/* Reviews */}\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <div className=\"mb-3 flex items-center justify-between\">\n <h2 className=\"flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Star className=\"h-4 w-4\" />\n Reviews ({reviewItems.length})\n </h2>\n {avgScore !== null && (\n <RatingDisplay value={avgScore / 2} count={reviewItems.length} />\n )}\n </div>\n {reviewItems.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">No reviews yet.</p>\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 </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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"}
@@ -7,12 +7,12 @@ import { formatEnumLabel as a } from "../../utils/formatters.js";
7
7
  import { ErrorState as o, LoadingState as s } from "../../components/StateViews.js";
8
8
  import { EmptyState as c } from "../../components/EmptyState.js";
9
9
  import { Pagination as l } from "../../components/Pagination.js";
10
- import { useState as u } from "react";
11
- import { Film as d, Plus as f, Search as p } from "lucide-react";
12
- import { jsx as m, jsxs as h } from "react/jsx-runtime";
13
- import { EmphasisPanel as g } from "@burdenoff/fe-libs/ui";
10
+ import { useEffect as u, useState as d } from "react";
11
+ import { Film as f, Plus as p, Search as m } from "lucide-react";
12
+ import { jsx as h, jsxs as g } from "react/jsx-runtime";
13
+ import { EmphasisPanel as _ } from "@burdenoff/fe-libs/ui";
14
14
  //#region src/hookmovies/pages/catalog/TitlesPage.tsx
15
- var _ = [
15
+ var v = [
16
16
  "MOVIE",
17
17
  "SERIES",
18
18
  "SHORT_FILM",
@@ -24,104 +24,125 @@ var _ = [
24
24
  "TRAILER",
25
25
  "COLLECTION",
26
26
  "FAST_CHANNEL"
27
- ], v = [
27
+ ], y = [
28
28
  "DRAFT",
29
29
  "IN_REVIEW",
30
30
  "SCHEDULED",
31
31
  "PUBLISHED",
32
32
  "UNPUBLISHED",
33
33
  "ARCHIVED"
34
- ], y = 20, b = () => {
35
- let { navigateTo: b } = e(), [x, S] = u(""), [C, w] = u(""), [T, E] = u(""), [D, O] = u(0), { data: k, isLoading: A, isError: j, refetch: M } = i({
36
- type: C || void 0,
37
- status: T || void 0
34
+ ], b = 20, x = () => {
35
+ let { navigateTo: x } = e(), [S, C] = d(""), [w, T] = d(""), [E, D] = d(""), [O, k] = d(""), [A, j] = d(0);
36
+ u(() => {
37
+ let e = window.setTimeout(() => T(S.trim()), 300);
38
+ return () => window.clearTimeout(e);
39
+ }, [S]), u(() => {
40
+ j(0);
41
+ }, [w]);
42
+ let { data: M, isLoading: N, isError: P, refetch: F } = i({
43
+ type: E || void 0,
44
+ status: O || void 0
38
45
  }, {
39
- limit: y,
40
- offset: D * y
41
- }), N = k?.items ?? [], P = x.trim() ? N.filter((e) => e.title.toLowerCase().includes(x.trim().toLowerCase())) : N;
42
- return /* @__PURE__ */ h(n, {
46
+ limit: b,
47
+ offset: A * b
48
+ }, w || void 0), I = M?.items ?? [], L = M?.totalCount ?? 0;
49
+ return /* @__PURE__ */ g(n, {
43
50
  title: "Catalog",
44
51
  description: "Movies, series, anime, documentaries & more",
45
52
  purpose: "The single source of truth for everything streamable in this workspace. Filter by type or status, then open a title to manage its credits, episodes, and publication lifecycle.",
46
- actions: /* @__PURE__ */ h("button", {
53
+ actions: /* @__PURE__ */ g("button", {
47
54
  type: "button",
48
- onClick: () => b("catalog/titles/new"),
55
+ onClick: () => x("catalog/titles/new"),
49
56
  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 transition-opacity",
50
- children: [/* @__PURE__ */ m(f, { className: "h-4 w-4" }), "New Title"]
57
+ children: [/* @__PURE__ */ h(p, { className: "h-4 w-4" }), "New Title"]
51
58
  }),
52
59
  children: [
53
- /* @__PURE__ */ m(g, { children: /* @__PURE__ */ h("div", {
60
+ /* @__PURE__ */ h(_, { children: /* @__PURE__ */ g("div", {
54
61
  className: "relative",
55
- children: [/* @__PURE__ */ m(p, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ m("input", {
56
- type: "text",
62
+ children: [/* @__PURE__ */ h(m, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ h("input", {
63
+ type: "search",
64
+ "aria-label": "Search titles",
57
65
  placeholder: "Search titles by name…",
58
- value: x,
59
- onChange: (e) => S(e.target.value),
66
+ value: S,
67
+ onChange: (e) => C(e.target.value),
60
68
  className: "w-full rounded-lg border border-border-subtle bg-bg-surface py-2.5 pl-10 pr-4 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
61
69
  })]
62
70
  }) }),
63
- /* @__PURE__ */ h("div", {
71
+ /* @__PURE__ */ g("div", {
64
72
  className: "mt-4 flex flex-wrap items-center gap-3",
65
- children: [/* @__PURE__ */ h("select", {
66
- value: C,
67
- onChange: (e) => {
68
- w(e.target.value), O(0);
69
- },
70
- className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
71
- children: [/* @__PURE__ */ m("option", {
72
- value: "",
73
- children: "Any Type"
74
- }), _.map((e) => /* @__PURE__ */ m("option", {
75
- value: e,
76
- children: a(e)
77
- }, e))]
78
- }), /* @__PURE__ */ h("select", {
79
- value: T,
80
- onChange: (e) => {
81
- E(e.target.value), O(0);
82
- },
83
- className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
84
- children: [/* @__PURE__ */ m("option", {
85
- value: "",
86
- children: "Any Status"
87
- }), v.map((e) => /* @__PURE__ */ m("option", {
88
- value: e,
89
- children: a(e)
90
- }, e))]
91
- })]
73
+ children: [
74
+ /* @__PURE__ */ g("select", {
75
+ value: E,
76
+ onChange: (e) => {
77
+ D(e.target.value), j(0);
78
+ },
79
+ className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
80
+ children: [/* @__PURE__ */ h("option", {
81
+ value: "",
82
+ children: "Any Type"
83
+ }), v.map((e) => /* @__PURE__ */ h("option", {
84
+ value: e,
85
+ children: a(e)
86
+ }, e))]
87
+ }),
88
+ /* @__PURE__ */ g("select", {
89
+ value: O,
90
+ onChange: (e) => {
91
+ k(e.target.value), j(0);
92
+ },
93
+ className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
94
+ children: [/* @__PURE__ */ h("option", {
95
+ value: "",
96
+ children: "Any Status"
97
+ }), y.map((e) => /* @__PURE__ */ h("option", {
98
+ value: e,
99
+ children: a(e)
100
+ }, e))]
101
+ }),
102
+ !N && !P && /* @__PURE__ */ g("p", {
103
+ className: "ml-auto text-xs text-text-secondary",
104
+ "aria-live": "polite",
105
+ children: [
106
+ L,
107
+ " ",
108
+ L === 1 ? "title" : "titles",
109
+ w ? ` matching “${w}”` : ""
110
+ ]
111
+ })
112
+ ]
92
113
  }),
93
- /* @__PURE__ */ h("div", {
114
+ /* @__PURE__ */ g("div", {
94
115
  className: "mt-6",
95
- children: [A ? /* @__PURE__ */ m(s, { label: "Loading catalog…" }) : j ? /* @__PURE__ */ m(o, {
116
+ children: [N ? /* @__PURE__ */ h(s, { label: "Loading catalog…" }) : P ? /* @__PURE__ */ h(o, {
96
117
  title: "Could not load titles",
97
118
  message: "The catalog service did not respond.",
98
- onRetry: () => void M()
99
- }) : P.length === 0 ? /* @__PURE__ */ m(c, {
119
+ onRetry: () => void F()
120
+ }) : I.length === 0 ? /* @__PURE__ */ h(c, {
100
121
  illustration: "empty-data",
101
- icon: /* @__PURE__ */ m(d, { className: "h-12 w-12" }),
122
+ icon: /* @__PURE__ */ h(f, { className: "h-12 w-12" }),
102
123
  title: "No titles found",
103
- description: x ? `No titles match "${x}".` : "No titles match these filters yet. Create your first title.",
104
- action: /* @__PURE__ */ m("button", {
124
+ description: w ? `No titles match "${w}".` : "No titles match these filters yet. Create your first title.",
125
+ action: /* @__PURE__ */ h("button", {
105
126
  type: "button",
106
- onClick: () => b("catalog/titles/new"),
127
+ onClick: () => x("catalog/titles/new"),
107
128
  className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 transition-opacity",
108
129
  children: "New Title"
109
130
  })
110
- }) : /* @__PURE__ */ m("div", {
131
+ }) : /* @__PURE__ */ h("div", {
111
132
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
112
- children: P.map((e) => /* @__PURE__ */ h("button", {
133
+ children: I.map((e) => /* @__PURE__ */ g("button", {
113
134
  type: "button",
114
- onClick: () => b(`catalog/titles/${e.id}`),
135
+ onClick: () => x(`catalog/titles/${e.id}`),
115
136
  className: t("flex flex-col rounded-lg border border-border-seam bg-bg-surface p-4 text-left", "hover:border-border-strong transition-colors"),
116
137
  children: [
117
- /* @__PURE__ */ h("div", {
138
+ /* @__PURE__ */ g("div", {
118
139
  className: "flex items-start justify-between gap-2",
119
- children: [/* @__PURE__ */ m("h3", {
140
+ children: [/* @__PURE__ */ h("h3", {
120
141
  className: "line-clamp-2 text-sm font-semibold text-text-primary",
121
142
  children: e.title
122
- }), /* @__PURE__ */ m(r, { status: e.status })]
143
+ }), /* @__PURE__ */ h(r, { status: e.status })]
123
144
  }),
124
- /* @__PURE__ */ h("p", {
145
+ /* @__PURE__ */ g("p", {
125
146
  className: "mt-1 text-xs text-text-secondary",
126
147
  children: [
127
148
  a(e.type),
@@ -129,30 +150,30 @@ var _ = [
129
150
  e.runtimeMinutes ? ` · ${e.runtimeMinutes} min` : ""
130
151
  ]
131
152
  }),
132
- e.synopsis && /* @__PURE__ */ m("p", {
153
+ e.synopsis && /* @__PURE__ */ h("p", {
133
154
  className: "mt-2 line-clamp-2 text-xs text-text-secondary",
134
155
  children: e.synopsis
135
156
  }),
136
- e.genres.length > 0 && /* @__PURE__ */ m("div", {
157
+ e.genres.length > 0 && /* @__PURE__ */ h("div", {
137
158
  className: "mt-3 flex flex-wrap gap-1",
138
- children: e.genres.slice(0, 3).map((e) => /* @__PURE__ */ m("span", {
159
+ children: e.genres.slice(0, 3).map((e) => /* @__PURE__ */ h("span", {
139
160
  className: "rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] text-text-secondary",
140
161
  children: e
141
162
  }, e))
142
163
  })
143
164
  ]
144
165
  }, e.id))
145
- }), !A && !j && !x && /* @__PURE__ */ m(l, {
146
- page: D,
147
- hasMore: k?.pageInfo.hasMore ?? !1,
148
- onPageChange: O,
149
- shownCount: N.length
166
+ }), !N && !P && /* @__PURE__ */ h(l, {
167
+ page: A,
168
+ hasMore: M?.pageInfo.hasMore ?? !1,
169
+ onPageChange: j,
170
+ shownCount: I.length
150
171
  })]
151
172
  })
152
173
  ]
153
174
  });
154
175
  };
155
176
  //#endregion
156
- export { b as TitlesPage };
177
+ export { x as TitlesPage };
157
178
 
158
179
  //# sourceMappingURL=TitlesPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TitlesPage.js","names":[],"sources":["../../../../src/hookmovies/pages/catalog/TitlesPage.tsx"],"sourcesContent":["/**\n * Titles list (Catalog)\n * @module hookmovies/pages/catalog\n *\n * Browse the workspace catalog via `hokListTitles` with type/status filters,\n * client-side text search, and offset pagination. Each row links to the title\n * detail page.\n */\n\nimport { type FC, useState } from 'react';\nimport { Search, Plus, Film } from 'lucide-react';\nimport { EmphasisPanel } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingState, ErrorState } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport { useHookMovies } from '../../context/HookMoviesContext';\nimport { useTitles, type HokTitleStatus, type HokTitleType } from '../../hooks/useHookMoviesApi';\nimport { cn } from '../../utils/cn';\nimport { formatEnumLabel } from '../../utils/formatters';\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 STATUS_OPTIONS: HokTitleStatus[] = [\n 'DRAFT',\n 'IN_REVIEW',\n 'SCHEDULED',\n 'PUBLISHED',\n 'UNPUBLISHED',\n 'ARCHIVED',\n];\n\nconst PAGE_LIMIT = 20;\n\nexport const TitlesPage: FC = () => {\n const { navigateTo } = useHookMovies();\n const [search, setSearch] = useState('');\n const [typeFilter, setTypeFilter] = useState<HokTitleType | ''>('');\n const [statusFilter, setStatusFilter] = useState<HokTitleStatus | ''>('');\n const [page, setPage] = useState(0);\n\n const { data, isLoading, isError, refetch } = useTitles(\n {\n type: typeFilter || undefined,\n status: statusFilter || undefined,\n },\n { limit: PAGE_LIMIT, offset: page * PAGE_LIMIT }\n );\n\n const items = data?.items ?? [];\n const filtered = search.trim()\n ? items.filter((t) => t.title.toLowerCase().includes(search.trim().toLowerCase()))\n : items;\n\n return (\n <PageLayout\n title=\"Catalog\"\n description=\"Movies, series, anime, documentaries & more\"\n purpose=\"The single source of truth for everything streamable in this workspace. Filter by type or status, then open a title to manage its credits, episodes, and publication lifecycle.\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('catalog/titles/new')}\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 transition-opacity\"\n >\n <Plus className=\"h-4 w-4\" />\n New Title\n </button>\n }\n >\n <EmphasisPanel>\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"text\"\n placeholder=\"Search titles by name…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2.5 pl-10 pr-4 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n </EmphasisPanel>\n\n <div className=\"mt-4 flex flex-wrap items-center gap-3\">\n <select\n value={typeFilter}\n onChange={(e) => {\n setTypeFilter(e.target.value as HokTitleType | '');\n setPage(0);\n }}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">Any Type</option>\n {TYPE_OPTIONS.map((t) => (\n <option key={t} value={t}>\n {formatEnumLabel(t)}\n </option>\n ))}\n </select>\n <select\n value={statusFilter}\n onChange={(e) => {\n setStatusFilter(e.target.value as HokTitleStatus | '');\n setPage(0);\n }}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">Any Status</option>\n {STATUS_OPTIONS.map((s) => (\n <option key={s} value={s}>\n {formatEnumLabel(s)}\n </option>\n ))}\n </select>\n </div>\n\n <div className=\"mt-6\">\n {isLoading ? (\n <LoadingState label=\"Loading catalog…\" />\n ) : isError ? (\n <ErrorState\n title=\"Could not load titles\"\n message=\"The catalog service did not respond.\"\n onRetry={() => void refetch()}\n />\n ) : filtered.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Film className=\"h-12 w-12\" />}\n title=\"No titles found\"\n description={\n search\n ? `No titles match \"${search}\".`\n : 'No titles match these filters yet. Create your first title.'\n }\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('catalog/titles/new')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 transition-opacity\"\n >\n New Title\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {filtered.map((title) => (\n <button\n key={title.id}\n type=\"button\"\n onClick={() => navigateTo(`catalog/titles/${title.id}`)}\n className={cn(\n 'flex flex-col rounded-lg border border-border-seam bg-bg-surface p-4 text-left',\n 'hover:border-border-strong transition-colors'\n )}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <h3 className=\"line-clamp-2 text-sm font-semibold text-text-primary\">\n {title.title}\n </h3>\n <StatusBadge status={title.status} />\n </div>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {formatEnumLabel(title.type)}\n {title.releaseYear ? ` · ${title.releaseYear}` : ''}\n {title.runtimeMinutes ? ` · ${title.runtimeMinutes} min` : ''}\n </p>\n {title.synopsis && (\n <p className=\"mt-2 line-clamp-2 text-xs text-text-secondary\">{title.synopsis}</p>\n )}\n {title.genres.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1\">\n {title.genres.slice(0, 3).map((g) => (\n <span\n key={g}\n className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] text-text-secondary\"\n >\n {g}\n </span>\n ))}\n </div>\n )}\n </button>\n ))}\n </div>\n )}\n\n {!isLoading && !isError && !search && (\n <Pagination\n page={page}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={setPage}\n shownCount={items.length}\n />\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"TitlesPage.js","names":[],"sources":["../../../../src/hookmovies/pages/catalog/TitlesPage.tsx"],"sourcesContent":["/**\n * Titles list (Catalog)\n * @module hookmovies/pages/catalog\n *\n * Browse the workspace catalog via `hokListTitles` with type/status filters,\n * server-side text search (debounced), and offset pagination. Each row links to\n * the title detail page.\n */\n\nimport { type FC, useEffect, useState } from 'react';\nimport { Search, Plus, Film } from 'lucide-react';\nimport { EmphasisPanel } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingState, ErrorState } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport { useHookMovies } from '../../context/HookMoviesContext';\nimport { useTitles, type HokTitleStatus, type HokTitleType } from '../../hooks/useHookMoviesApi';\nimport { cn } from '../../utils/cn';\nimport { formatEnumLabel } from '../../utils/formatters';\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 STATUS_OPTIONS: HokTitleStatus[] = [\n 'DRAFT',\n 'IN_REVIEW',\n 'SCHEDULED',\n 'PUBLISHED',\n 'UNPUBLISHED',\n 'ARCHIVED',\n];\n\nconst PAGE_LIMIT = 20;\n\nexport const TitlesPage: FC = () => {\n const { navigateTo } = useHookMovies();\n const [search, setSearch] = useState('');\n const [debouncedSearch, setDebouncedSearch] = useState('');\n const [typeFilter, setTypeFilter] = useState<HokTitleType | ''>('');\n const [statusFilter, setStatusFilter] = useState<HokTitleStatus | ''>('');\n const [page, setPage] = useState(0);\n\n // Debounce the search box (~300ms) so each keystroke doesn't fire a query.\n useEffect(() => {\n const handle = window.setTimeout(() => setDebouncedSearch(search.trim()), 300);\n return () => window.clearTimeout(handle);\n }, [search]);\n\n // Reset to the first page whenever the effective (debounced) search changes,\n // so server-side results always start from the top of the filtered set.\n useEffect(() => {\n setPage(0);\n }, [debouncedSearch]);\n\n const { data, isLoading, isError, refetch } = useTitles(\n {\n type: typeFilter || undefined,\n status: statusFilter || undefined,\n },\n { limit: PAGE_LIMIT, offset: page * PAGE_LIMIT },\n debouncedSearch || undefined\n );\n\n const items = data?.items ?? [];\n const totalCount = data?.totalCount ?? 0;\n\n return (\n <PageLayout\n title=\"Catalog\"\n description=\"Movies, series, anime, documentaries & more\"\n purpose=\"The single source of truth for everything streamable in this workspace. Filter by type or status, then open a title to manage its credits, episodes, and publication lifecycle.\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('catalog/titles/new')}\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 transition-opacity\"\n >\n <Plus className=\"h-4 w-4\" />\n New Title\n </button>\n }\n >\n <EmphasisPanel>\n <div className=\"relative\">\n <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary\" />\n <input\n type=\"search\"\n aria-label=\"Search titles\"\n placeholder=\"Search titles by name…\"\n value={search}\n onChange={(e) => setSearch(e.target.value)}\n className=\"w-full rounded-lg border border-border-subtle bg-bg-surface py-2.5 pl-10 pr-4 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n </EmphasisPanel>\n\n <div className=\"mt-4 flex flex-wrap items-center gap-3\">\n <select\n value={typeFilter}\n onChange={(e) => {\n setTypeFilter(e.target.value as HokTitleType | '');\n setPage(0);\n }}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">Any Type</option>\n {TYPE_OPTIONS.map((t) => (\n <option key={t} value={t}>\n {formatEnumLabel(t)}\n </option>\n ))}\n </select>\n <select\n value={statusFilter}\n onChange={(e) => {\n setStatusFilter(e.target.value as HokTitleStatus | '');\n setPage(0);\n }}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">Any Status</option>\n {STATUS_OPTIONS.map((s) => (\n <option key={s} value={s}>\n {formatEnumLabel(s)}\n </option>\n ))}\n </select>\n {!isLoading && !isError && (\n <p className=\"ml-auto text-xs text-text-secondary\" aria-live=\"polite\">\n {totalCount} {totalCount === 1 ? 'title' : 'titles'}\n {debouncedSearch ? ` matching “${debouncedSearch}”` : ''}\n </p>\n )}\n </div>\n\n <div className=\"mt-6\">\n {isLoading ? (\n <LoadingState label=\"Loading catalog…\" />\n ) : isError ? (\n <ErrorState\n title=\"Could not load titles\"\n message=\"The catalog service did not respond.\"\n onRetry={() => void refetch()}\n />\n ) : items.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n icon={<Film className=\"h-12 w-12\" />}\n title=\"No titles found\"\n description={\n debouncedSearch\n ? `No titles match \"${debouncedSearch}\".`\n : 'No titles match these filters yet. Create your first title.'\n }\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('catalog/titles/new')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 transition-opacity\"\n >\n New Title\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {items.map((title) => (\n <button\n key={title.id}\n type=\"button\"\n onClick={() => navigateTo(`catalog/titles/${title.id}`)}\n className={cn(\n 'flex flex-col rounded-lg border border-border-seam bg-bg-surface p-4 text-left',\n 'hover:border-border-strong transition-colors'\n )}\n >\n <div className=\"flex items-start justify-between gap-2\">\n <h3 className=\"line-clamp-2 text-sm font-semibold text-text-primary\">\n {title.title}\n </h3>\n <StatusBadge status={title.status} />\n </div>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {formatEnumLabel(title.type)}\n {title.releaseYear ? ` · ${title.releaseYear}` : ''}\n {title.runtimeMinutes ? ` · ${title.runtimeMinutes} min` : ''}\n </p>\n {title.synopsis && (\n <p className=\"mt-2 line-clamp-2 text-xs text-text-secondary\">{title.synopsis}</p>\n )}\n {title.genres.length > 0 && (\n <div className=\"mt-3 flex flex-wrap gap-1\">\n {title.genres.slice(0, 3).map((g) => (\n <span\n key={g}\n className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-[10px] text-text-secondary\"\n >\n {g}\n </span>\n ))}\n </div>\n )}\n </button>\n ))}\n </div>\n )}\n\n {!isLoading && !isError && (\n <Pagination\n page={page}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={setPage}\n shownCount={items.length}\n />\n )}\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
@@ -24,7 +24,7 @@ var v = [
24
24
  "PPV",
25
25
  "FAST"
26
26
  ], b = {
27
- DRAFT: ["PENDING", "ACTIVE"],
27
+ DRAFT: ["PENDING", "REVOKED"],
28
28
  PENDING: ["ACTIVE", "REVOKED"],
29
29
  ACTIVE: ["EXPIRED", "REVOKED"],
30
30
  EXPIRED: [],