@burdenoff/microfe-hookmovies 2026.706.2 → 2026.706.4

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.
Files changed (62) hide show
  1. package/dist/hookmovies/HookMoviesRoutes.js +54 -6
  2. package/dist/hookmovies/HookMoviesRoutes.js.map +1 -1
  3. package/dist/hookmovies/components/index.js +1 -1
  4. package/dist/hookmovies/context/HookMoviesContext.js +64 -40
  5. package/dist/hookmovies/context/HookMoviesContext.js.map +1 -1
  6. package/dist/hookmovies/hooks/useHookMoviesApi.js +592 -134
  7. package/dist/hookmovies/hooks/useHookMoviesApi.js.map +1 -1
  8. package/dist/hookmovies/pages/HomePage.js +211 -139
  9. package/dist/hookmovies/pages/HomePage.js.map +1 -1
  10. package/dist/hookmovies/pages/ai/ConciergePage.js +330 -0
  11. package/dist/hookmovies/pages/ai/ConciergePage.js.map +1 -0
  12. package/dist/hookmovies/pages/analytics/AnalyticsPage.js +450 -0
  13. package/dist/hookmovies/pages/analytics/AnalyticsPage.js.map +1 -0
  14. package/dist/hookmovies/pages/analytics/PayoutsPage.js +499 -0
  15. package/dist/hookmovies/pages/analytics/PayoutsPage.js.map +1 -0
  16. package/dist/hookmovies/pages/auditions/AuditionDetailPage.js +223 -140
  17. package/dist/hookmovies/pages/auditions/AuditionDetailPage.js.map +1 -1
  18. package/dist/hookmovies/pages/auditions/AuditionsPage.js +161 -83
  19. package/dist/hookmovies/pages/auditions/AuditionsPage.js.map +1 -1
  20. package/dist/hookmovies/pages/catalog/PeoplePage.js +177 -103
  21. package/dist/hookmovies/pages/catalog/PeoplePage.js.map +1 -1
  22. package/dist/hookmovies/pages/catalog/StudiosPage.js +191 -108
  23. package/dist/hookmovies/pages/catalog/StudiosPage.js.map +1 -1
  24. package/dist/hookmovies/pages/catalog/TitleDetailPage.js +744 -622
  25. package/dist/hookmovies/pages/catalog/TitleDetailPage.js.map +1 -1
  26. package/dist/hookmovies/pages/catalog/TitlesPage.js +218 -138
  27. package/dist/hookmovies/pages/catalog/TitlesPage.js.map +1 -1
  28. package/dist/hookmovies/pages/commerce/CheckoutPage.js +430 -0
  29. package/dist/hookmovies/pages/commerce/CheckoutPage.js.map +1 -0
  30. package/dist/hookmovies/pages/consumer/DiscoveryPage.js +21 -21
  31. package/dist/hookmovies/pages/consumer/HooksPage.js +5 -5
  32. package/dist/hookmovies/pages/consumer/TitleViewPage.js +32 -32
  33. package/dist/hookmovies/pages/consumer/TitleViewPage.js.map +1 -1
  34. package/dist/hookmovies/pages/developer/DevPortalPage.js +815 -0
  35. package/dist/hookmovies/pages/developer/DevPortalPage.js.map +1 -0
  36. package/dist/hookmovies/pages/distribution/RightsWindowsPage.js +235 -162
  37. package/dist/hookmovies/pages/distribution/RightsWindowsPage.js.map +1 -1
  38. package/dist/hookmovies/pages/engagement/ReviewsPage.js +201 -143
  39. package/dist/hookmovies/pages/engagement/ReviewsPage.js.map +1 -1
  40. package/dist/hookmovies/pages/library/EntitlementsPage.js +447 -221
  41. package/dist/hookmovies/pages/library/EntitlementsPage.js.map +1 -1
  42. package/dist/hookmovies/pages/library/ListsPage.js +243 -167
  43. package/dist/hookmovies/pages/library/ListsPage.js.map +1 -1
  44. package/dist/hookmovies/pages/live/LivePage.js +608 -0
  45. package/dist/hookmovies/pages/live/LivePage.js.map +1 -0
  46. package/dist/hookmovies/pages/localization/LocalizationPage.js +656 -0
  47. package/dist/hookmovies/pages/localization/LocalizationPage.js.map +1 -0
  48. package/dist/hookmovies/pages/onboarding/OnboardingPage.js +366 -0
  49. package/dist/hookmovies/pages/onboarding/OnboardingPage.js.map +1 -0
  50. package/dist/hookmovies/pages/productions/ProductionDetailPage.js +265 -179
  51. package/dist/hookmovies/pages/productions/ProductionDetailPage.js.map +1 -1
  52. package/dist/hookmovies/pages/productions/ProductionsPage.js +264 -71
  53. package/dist/hookmovies/pages/productions/ProductionsPage.js.map +1 -1
  54. package/dist/hookmovies/pages/social/ProfilesPage.js +701 -0
  55. package/dist/hookmovies/pages/social/ProfilesPage.js.map +1 -0
  56. package/dist/hookmovies/pages/social/WatchPartyListPage.js +281 -0
  57. package/dist/hookmovies/pages/social/WatchPartyListPage.js.map +1 -0
  58. package/dist/hookmovies/pages/social/WatchPartyRoomPage.js +567 -0
  59. package/dist/hookmovies/pages/social/WatchPartyRoomPage.js.map +1 -0
  60. package/dist/hookmovies/pages/trust/ModerationPage.js +320 -0
  61. package/dist/hookmovies/pages/trust/ModerationPage.js.map +1 -0
  62. package/package.json +1 -1
@@ -0,0 +1,656 @@
1
+ import { useHookMovies as e } from "../../context/HookMoviesContext.js";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { PageLayout as n } from "../../components/PageLayout.js";
4
+ import { StatusBadge as r } from "../../components/StatusBadge.js";
5
+ import { useCreateLocalization as i, useDeleteLocalization as a, useLanguages as o, useLocalizations as s, useSetDefaultLocalization as c, useTitle as ee, useTransitionTitle as te, useUpdateTitle as ne } from "../../hooks/useHookMoviesApi.js";
6
+ import { uploadFileToFiles as re, useFileUrl as l } from "../../hooks/useFiles.js";
7
+ import { formatDate as ie, formatEnumLabel as u } from "../../utils/formatters.js";
8
+ import { EmptyState as ae } from "../../components/EmptyState.js";
9
+ import { ErrorState as oe, LoadingState as d } from "../../components/StateViews.js";
10
+ import { useMemo as se, useRef as ce, useState as f } from "react";
11
+ import { ArrowLeft as le, CalendarClock as ue, Captions as p, CheckCircle2 as m, Download as h, Languages as de, Loader2 as g, Mic as _, Plus as fe, Rocket as pe, Star as v, Trash2 as y, Upload as me, X as he } from "lucide-react";
12
+ import { useParams as ge } from "react-router-dom";
13
+ import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
14
+ import { GlassCard as _e } from "@burdenoff/fe-libs/ui";
15
+ //#region src/hookmovies/pages/localization/LocalizationPage.tsx
16
+ var C = [
17
+ "DRAFT",
18
+ "IN_REVIEW",
19
+ "SCHEDULED",
20
+ "PUBLISHED"
21
+ ], w = {
22
+ DRAFT: ["IN_REVIEW", "ARCHIVED"],
23
+ IN_REVIEW: [
24
+ "SCHEDULED",
25
+ "PUBLISHED",
26
+ "DRAFT",
27
+ "ARCHIVED"
28
+ ],
29
+ SCHEDULED: [
30
+ "PUBLISHED",
31
+ "IN_REVIEW",
32
+ "ARCHIVED"
33
+ ],
34
+ PUBLISHED: ["UNPUBLISHED", "ARCHIVED"],
35
+ UNPUBLISHED: ["PUBLISHED", "ARCHIVED"],
36
+ ARCHIVED: []
37
+ }, T = {
38
+ SUBTITLE: {
39
+ label: "Subtitle",
40
+ icon: p,
41
+ folder: "/HookMovies/Subtitles",
42
+ accept: ".vtt,.srt,text/vtt,application/x-subrip",
43
+ hint: "Timed-text subtitles (.vtt or .srt)."
44
+ },
45
+ CAPTION: {
46
+ label: "Caption (SDH)",
47
+ icon: p,
48
+ folder: "/HookMovies/Subtitles",
49
+ accept: ".vtt,.srt,text/vtt,application/x-subrip",
50
+ hint: "Captions for deaf / hard-of-hearing viewers (.vtt or .srt)."
51
+ },
52
+ DUB: {
53
+ label: "Dub",
54
+ icon: _,
55
+ folder: "/HookMovies/Dubs",
56
+ accept: "audio/*",
57
+ hint: "Localized audio track (dubbed)."
58
+ }
59
+ }, E = [
60
+ "SUBTITLE",
61
+ "CAPTION",
62
+ "DUB"
63
+ ], D = "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)]", O = "mb-1.5 block text-xs font-medium text-text-secondary";
64
+ function ve(e) {
65
+ if (!e) return "";
66
+ let t = new Date(e);
67
+ if (Number.isNaN(t.getTime())) return "";
68
+ let n = (e) => String(e).padStart(2, "0");
69
+ return `${t.getFullYear()}-${n(t.getMonth() + 1)}-${n(t.getDate())}T${n(t.getHours())}:${n(t.getMinutes())}`;
70
+ }
71
+ var ye = ({ track: e, onSetDefault: t, onDelete: n, settingDefault: i, deleting: a }) => {
72
+ let o = l(e.fileId), s = T[e.kind], c = s.icon;
73
+ return /* @__PURE__ */ S("tr", {
74
+ className: "border-t border-border-seam",
75
+ children: [
76
+ /* @__PURE__ */ x("td", {
77
+ className: "whitespace-nowrap px-4 py-3",
78
+ children: /* @__PURE__ */ S("span", {
79
+ className: "inline-flex items-center gap-2 text-sm font-medium text-text-primary",
80
+ children: [/* @__PURE__ */ x("span", {
81
+ className: "rounded-md bg-bg-sunken px-2 py-0.5 text-xs uppercase tracking-wide text-text-secondary",
82
+ children: e.language
83
+ }), e.localizedTitle && /* @__PURE__ */ x("span", {
84
+ className: "truncate text-xs text-text-secondary",
85
+ children: e.localizedTitle
86
+ })]
87
+ })
88
+ }),
89
+ /* @__PURE__ */ x("td", {
90
+ className: "whitespace-nowrap px-4 py-3",
91
+ children: /* @__PURE__ */ S("span", {
92
+ className: "inline-flex items-center gap-1.5 text-sm text-text-primary",
93
+ children: [/* @__PURE__ */ x(c, {
94
+ className: "h-3.5 w-3.5 text-text-secondary",
95
+ "aria-hidden": "true"
96
+ }), s.label]
97
+ })
98
+ }),
99
+ /* @__PURE__ */ x("td", {
100
+ className: "whitespace-nowrap px-4 py-3",
101
+ children: /* @__PURE__ */ x(r, { status: e.status })
102
+ }),
103
+ /* @__PURE__ */ x("td", {
104
+ className: "whitespace-nowrap px-4 py-3",
105
+ children: e.isDefault ? /* @__PURE__ */ S("span", {
106
+ className: "inline-flex items-center gap-1 rounded-full bg-status-success-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-success-text",
107
+ children: [/* @__PURE__ */ x(v, {
108
+ className: "h-3 w-3 fill-current",
109
+ "aria-hidden": "true"
110
+ }), "Default"]
111
+ }) : /* @__PURE__ */ S("button", {
112
+ type: "button",
113
+ disabled: i,
114
+ onClick: () => t(e),
115
+ 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",
116
+ children: [/* @__PURE__ */ x(v, {
117
+ className: "h-3.5 w-3.5",
118
+ "aria-hidden": "true"
119
+ }), "Make default"]
120
+ })
121
+ }),
122
+ /* @__PURE__ */ x("td", {
123
+ className: "whitespace-nowrap px-4 py-3",
124
+ children: o.isLoading ? /* @__PURE__ */ S("span", {
125
+ className: "inline-flex items-center gap-1.5 text-xs text-text-secondary",
126
+ children: [/* @__PURE__ */ x(g, {
127
+ className: "h-3.5 w-3.5 animate-spin",
128
+ "aria-hidden": "true"
129
+ }), "Resolving…"]
130
+ }) : o.data ? /* @__PURE__ */ S("a", {
131
+ href: o.data,
132
+ target: "_blank",
133
+ rel: "noreferrer",
134
+ download: !0,
135
+ 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",
136
+ children: [/* @__PURE__ */ x(h, {
137
+ className: "h-3.5 w-3.5",
138
+ "aria-hidden": "true"
139
+ }), "File"]
140
+ }) : /* @__PURE__ */ x("span", {
141
+ className: "text-xs text-text-muted",
142
+ children: "Unavailable"
143
+ })
144
+ }),
145
+ /* @__PURE__ */ x("td", {
146
+ className: "whitespace-nowrap px-4 py-3 text-right",
147
+ children: /* @__PURE__ */ S("button", {
148
+ type: "button",
149
+ disabled: a,
150
+ onClick: () => n(e),
151
+ "aria-label": `Delete ${s.label} track (${e.language})`,
152
+ 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",
153
+ children: [a ? /* @__PURE__ */ x(g, {
154
+ className: "h-3.5 w-3.5 animate-spin",
155
+ "aria-hidden": "true"
156
+ }) : /* @__PURE__ */ x(y, {
157
+ className: "h-3.5 w-3.5",
158
+ "aria-hidden": "true"
159
+ }), "Delete"]
160
+ })
161
+ })
162
+ ]
163
+ });
164
+ }, k = () => {
165
+ let { id: l } = ge(), { navigateTo: h } = e(), { data: _, isLoading: v, isError: y, refetch: k } = ee(l), A = ne(), j = te(), M = s(l), be = i(), xe = c(), Se = a(), N = o({ status: "ACTIVE" }, 200, 0), [Ce, we] = f(""), [Te, P] = f(!1), [Ee, F] = f(!1), [I, L] = f(null), [R, z] = f(!1), [B, V] = f(""), [H, De] = f("SUBTITLE"), [U, W] = f(null), [G, K] = f(""), [Oe, ke] = f(""), [Ae, je] = f(!1), [Me, Ne] = f(!1), [Pe, q] = f(null), J = ce(null), [Fe, Ie] = f(null), [Le, Re] = f(null), [Y, X] = f(null), ze = N.data?.items ?? [], Z = se(() => [...M.data ?? []].sort((e, t) => {
166
+ let n = E.indexOf(e.kind) - E.indexOf(t.kind);
167
+ return n === 0 ? e.language.localeCompare(t.language) : n;
168
+ }), [M.data]);
169
+ if (v) return /* @__PURE__ */ x(n, {
170
+ title: "Publishing & Localization",
171
+ children: /* @__PURE__ */ x(d, { label: "Loading title…" })
172
+ });
173
+ if (y || !_) return /* @__PURE__ */ x(n, {
174
+ title: "Publishing & Localization",
175
+ children: /* @__PURE__ */ x(oe, {
176
+ title: "Title not found",
177
+ message: "This title may have been archived, or you may not have access to it.",
178
+ onRetry: () => void k()
179
+ })
180
+ });
181
+ let Q = Te ? Ce : ve(_.releaseDate), Be = C.indexOf(_.status), Ve = Be === -1, He = async (e) => {
182
+ e.preventDefault(), L(null), F(!1);
183
+ let t = { releaseDate: Q.trim() ? new Date(Q).toISOString() : null };
184
+ try {
185
+ await A.mutateAsync({
186
+ id: _.id,
187
+ input: t
188
+ }), P(!1), F(!0);
189
+ } catch (e) {
190
+ L(e instanceof Error ? e.message : "Could not save the release date.");
191
+ }
192
+ }, Ue = async (e) => {
193
+ L(null);
194
+ try {
195
+ await j.mutateAsync({
196
+ id: _.id,
197
+ status: e
198
+ });
199
+ } catch (e) {
200
+ L(e instanceof Error ? e.message : "Transition failed.");
201
+ }
202
+ }, We = () => {
203
+ V(""), De("SUBTITLE"), W(null), K(""), ke(""), je(!1), q(null), J.current && (J.current.value = "");
204
+ }, Ge = (e) => {
205
+ W(e.target.files?.[0] ?? null);
206
+ }, Ke = async (e) => {
207
+ if (e.preventDefault(), q(null), !B.trim()) {
208
+ q("Select a language.");
209
+ return;
210
+ }
211
+ if (!U) {
212
+ q("Choose a track file to upload.");
213
+ return;
214
+ }
215
+ Ne(!0);
216
+ try {
217
+ let e = await re(U, T[H].folder);
218
+ await be.mutateAsync({
219
+ titleId: _.id,
220
+ language: B.trim(),
221
+ kind: H,
222
+ fileId: e.id,
223
+ isDefault: Ae,
224
+ localizedTitle: G.trim() || void 0,
225
+ localizedSynopsis: Oe.trim() || void 0
226
+ }), We(), z(!1);
227
+ } catch (e) {
228
+ q(e instanceof Error ? e.message : "Failed to add localization track.");
229
+ } finally {
230
+ Ne(!1);
231
+ }
232
+ }, qe = async (e) => {
233
+ X(null), Ie(e.id);
234
+ try {
235
+ await xe.mutateAsync(e.id);
236
+ } catch (e) {
237
+ X(e instanceof Error ? e.message : "Could not set default track.");
238
+ } finally {
239
+ Ie(null);
240
+ }
241
+ }, Je = async (e) => {
242
+ X(null), Re(e.id);
243
+ try {
244
+ await Se.mutateAsync(e.id);
245
+ } catch (e) {
246
+ X(e instanceof Error ? e.message : "Could not delete track.");
247
+ } finally {
248
+ Re(null);
249
+ }
250
+ }, $ = T[H];
251
+ return /* @__PURE__ */ S(n, {
252
+ title: /* @__PURE__ */ S("span", {
253
+ className: "flex items-center gap-3",
254
+ children: [/* @__PURE__ */ x("button", {
255
+ type: "button",
256
+ onClick: () => h(`catalog/titles/${_.id}`),
257
+ className: "rounded-md p-1 text-text-secondary transition-colors hover:text-text-primary",
258
+ "aria-label": "Back to title",
259
+ children: /* @__PURE__ */ x(le, { className: "h-5 w-5" })
260
+ }), "Publishing & Localization"]
261
+ }),
262
+ description: _.title,
263
+ purpose: "Schedule the release, walk the title through its publication lifecycle, and manage the per-language subtitle, caption and dub tracks the player offers viewers.",
264
+ actions: /* @__PURE__ */ x(r, { status: _.status }),
265
+ children: [
266
+ I && /* @__PURE__ */ x("div", {
267
+ 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",
268
+ children: I
269
+ }),
270
+ /* @__PURE__ */ S(_e, {
271
+ treatment: "metric",
272
+ className: "mb-6 border-border-seam p-5",
273
+ children: [
274
+ /* @__PURE__ */ S("div", {
275
+ className: "mb-5 flex items-center gap-2",
276
+ children: [/* @__PURE__ */ x(pe, {
277
+ className: "h-4 w-4 text-text-secondary",
278
+ "aria-hidden": "true"
279
+ }), /* @__PURE__ */ x("h2", {
280
+ className: "text-sm font-semibold text-text-primary",
281
+ children: "Release scheduler"
282
+ })]
283
+ }),
284
+ /* @__PURE__ */ x("ol", {
285
+ className: "mb-6 flex flex-col gap-3 sm:flex-row sm:items-center sm:gap-0",
286
+ children: C.map((e, n) => {
287
+ let r = !Ve && n < Be, i = e === _.status;
288
+ return /* @__PURE__ */ S("li", {
289
+ className: "flex items-center sm:flex-1",
290
+ children: [/* @__PURE__ */ S("div", {
291
+ className: "flex items-center gap-2",
292
+ children: [/* @__PURE__ */ x("span", {
293
+ className: t("flex h-7 w-7 shrink-0 items-center justify-center rounded-full border text-xs font-semibold", i ? "bg-action-primary-bg text-action-primary-text border-transparent" : r ? "bg-status-success-bg-subtle text-status-success-text border-transparent" : "bg-bg-sunken text-text-secondary border-border-seam"),
294
+ "aria-current": i ? "step" : void 0,
295
+ children: r ? /* @__PURE__ */ x(m, {
296
+ className: "h-4 w-4",
297
+ "aria-hidden": "true"
298
+ }) : n + 1
299
+ }), /* @__PURE__ */ x("span", {
300
+ className: t("text-xs font-medium", i ? "text-text-primary" : "text-text-secondary"),
301
+ children: u(e)
302
+ })]
303
+ }), n < C.length - 1 && /* @__PURE__ */ x("span", {
304
+ "aria-hidden": "true",
305
+ className: t("mx-3 hidden h-px flex-1 sm:block", r ? "bg-status-success-border" : "bg-border-seam")
306
+ })]
307
+ }, e);
308
+ })
309
+ }),
310
+ Ve && /* @__PURE__ */ S("p", {
311
+ className: "mb-4 rounded-lg border border-border-seam bg-bg-sunken px-3 py-2 text-xs text-text-secondary",
312
+ children: [
313
+ "This title is currently",
314
+ " ",
315
+ /* @__PURE__ */ x("span", {
316
+ className: "font-medium",
317
+ children: u(_.status)
318
+ }),
319
+ " — outside the standard release pipeline. Use the actions below to move it back."
320
+ ]
321
+ }),
322
+ /* @__PURE__ */ S("div", {
323
+ className: "grid grid-cols-1 gap-6 lg:grid-cols-2",
324
+ children: [/* @__PURE__ */ S("form", {
325
+ onSubmit: He,
326
+ className: "space-y-3",
327
+ children: [/* @__PURE__ */ S("div", { children: [
328
+ /* @__PURE__ */ x("label", {
329
+ htmlFor: "release-date",
330
+ className: O,
331
+ children: /* @__PURE__ */ S("span", {
332
+ className: "inline-flex items-center gap-1.5",
333
+ children: [/* @__PURE__ */ x(ue, {
334
+ className: "h-3.5 w-3.5",
335
+ "aria-hidden": "true"
336
+ }), "Release date & time"]
337
+ })
338
+ }),
339
+ /* @__PURE__ */ x("input", {
340
+ id: "release-date",
341
+ type: "datetime-local",
342
+ value: Q,
343
+ onChange: (e) => {
344
+ we(e.target.value), P(!0), F(!1);
345
+ },
346
+ className: D
347
+ }),
348
+ /* @__PURE__ */ x("p", {
349
+ className: "mt-1 text-[11px] text-text-secondary",
350
+ children: _.releaseDate ? `Currently scheduled for ${ie(_.releaseDate)}.` : "No release date set yet. Leave empty and save to clear."
351
+ })
352
+ ] }), /* @__PURE__ */ S("div", {
353
+ className: "flex items-center gap-3",
354
+ children: [/* @__PURE__ */ x("button", {
355
+ type: "submit",
356
+ disabled: A.isPending,
357
+ 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",
358
+ children: A.isPending ? /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ x(g, {
359
+ className: "h-4 w-4 animate-spin",
360
+ "aria-hidden": "true"
361
+ }), "Saving…"] }) : "Save release date"
362
+ }), Ee && /* @__PURE__ */ S("span", {
363
+ className: "inline-flex items-center gap-1.5 text-sm text-status-success-text",
364
+ children: [/* @__PURE__ */ x(m, {
365
+ className: "h-4 w-4",
366
+ "aria-hidden": "true"
367
+ }), "Saved"]
368
+ })]
369
+ })]
370
+ }), /* @__PURE__ */ S("div", { children: [
371
+ /* @__PURE__ */ x("span", {
372
+ className: O,
373
+ children: "Publication actions"
374
+ }),
375
+ w[_.status].length === 0 ? /* @__PURE__ */ S("p", {
376
+ className: "text-sm text-text-secondary",
377
+ children: [
378
+ "No further transitions available from ",
379
+ u(_.status),
380
+ "."
381
+ ]
382
+ }) : /* @__PURE__ */ x("div", {
383
+ className: "flex flex-wrap gap-2",
384
+ children: w[_.status].map((e) => {
385
+ let n = e === "ARCHIVED";
386
+ return /* @__PURE__ */ S("button", {
387
+ type: "button",
388
+ disabled: j.isPending,
389
+ onClick: () => void Ue(e),
390
+ className: t("rounded-lg px-3 py-1.5 text-xs font-medium transition-opacity disabled:opacity-50", n ? "border border-status-error-border text-status-error-text hover:bg-status-error-bg-subtle" : "bg-action-primary-bg text-action-primary-text hover:opacity-90"),
391
+ children: ["Move to ", u(e)]
392
+ }, e);
393
+ })
394
+ }),
395
+ /* @__PURE__ */ S("p", {
396
+ className: "mt-2 text-[11px] text-text-secondary",
397
+ children: [
398
+ "Set a release date, then move the title to",
399
+ " ",
400
+ /* @__PURE__ */ x("span", {
401
+ className: "font-medium",
402
+ children: "Scheduled"
403
+ }),
404
+ " and finally",
405
+ " ",
406
+ /* @__PURE__ */ x("span", {
407
+ className: "font-medium",
408
+ children: "Published"
409
+ }),
410
+ " to make it live."
411
+ ]
412
+ })
413
+ ] })]
414
+ })
415
+ ]
416
+ }),
417
+ /* @__PURE__ */ S(_e, {
418
+ treatment: "metric",
419
+ className: "border-border-seam p-5",
420
+ children: [
421
+ /* @__PURE__ */ S("div", {
422
+ className: "mb-4 flex flex-wrap items-center justify-between gap-3",
423
+ children: [/* @__PURE__ */ S("div", {
424
+ className: "flex items-center gap-2",
425
+ children: [/* @__PURE__ */ x(de, {
426
+ className: "h-4 w-4 text-text-secondary",
427
+ "aria-hidden": "true"
428
+ }), /* @__PURE__ */ S("h2", {
429
+ className: "text-sm font-semibold text-text-primary",
430
+ children: [
431
+ "Localization tracks (",
432
+ Z.length,
433
+ ")"
434
+ ]
435
+ })]
436
+ }), /* @__PURE__ */ S("button", {
437
+ type: "button",
438
+ onClick: () => {
439
+ z((e) => !e), q(null);
440
+ },
441
+ 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",
442
+ children: [x(R ? he : fe, { className: "h-4 w-4" }), R ? "Close" : "Add track"]
443
+ })]
444
+ }),
445
+ R && /* @__PURE__ */ S("form", {
446
+ onSubmit: Ke,
447
+ className: "mb-6 space-y-4 rounded-xl border border-border-seam bg-bg-surface p-4",
448
+ children: [
449
+ /* @__PURE__ */ S("div", {
450
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
451
+ children: [/* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("label", {
452
+ htmlFor: "loc-language",
453
+ className: O,
454
+ children: "Language *"
455
+ }), ze.length > 0 ? /* @__PURE__ */ S("select", {
456
+ id: "loc-language",
457
+ value: B,
458
+ onChange: (e) => V(e.target.value),
459
+ className: D,
460
+ required: !0,
461
+ children: [/* @__PURE__ */ x("option", {
462
+ value: "",
463
+ children: N.isLoading ? "Loading languages…" : "Select a language…"
464
+ }), ze.map((e) => /* @__PURE__ */ S("option", {
465
+ value: e.code,
466
+ children: [
467
+ e.name,
468
+ e.nativeName && e.nativeName !== e.name ? ` — ${e.nativeName}` : "",
469
+ " ",
470
+ "(",
471
+ e.code,
472
+ ")"
473
+ ]
474
+ }, e.id))]
475
+ }) : /* @__PURE__ */ x("input", {
476
+ id: "loc-language",
477
+ type: "text",
478
+ value: B,
479
+ onChange: (e) => V(e.target.value),
480
+ placeholder: N.isLoading ? "Loading languages…" : "e.g. en, hi, ta",
481
+ className: D,
482
+ required: !0
483
+ })] }), /* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("label", {
484
+ htmlFor: "loc-kind",
485
+ className: O,
486
+ children: "Track type *"
487
+ }), /* @__PURE__ */ x("select", {
488
+ id: "loc-kind",
489
+ value: H,
490
+ onChange: (e) => {
491
+ De(e.target.value), W(null), J.current && (J.current.value = "");
492
+ },
493
+ className: D,
494
+ children: E.map((e) => /* @__PURE__ */ x("option", {
495
+ value: e,
496
+ children: T[e].label
497
+ }, e))
498
+ })] })]
499
+ }),
500
+ /* @__PURE__ */ S("div", { children: [
501
+ /* @__PURE__ */ x("label", {
502
+ htmlFor: "loc-file",
503
+ className: O,
504
+ children: "Track file *"
505
+ }),
506
+ /* @__PURE__ */ x("input", {
507
+ id: "loc-file",
508
+ ref: J,
509
+ type: "file",
510
+ accept: $.accept,
511
+ onChange: Ge,
512
+ className: D
513
+ }),
514
+ /* @__PURE__ */ x("p", {
515
+ className: "mt-1 text-[11px] text-text-secondary",
516
+ children: $.hint
517
+ }),
518
+ U && /* @__PURE__ */ S("p", {
519
+ className: "mt-1 truncate text-xs text-text-secondary",
520
+ children: ["Selected: ", U.name]
521
+ })
522
+ ] }),
523
+ /* @__PURE__ */ S("div", {
524
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
525
+ children: [/* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("label", {
526
+ htmlFor: "loc-title",
527
+ className: O,
528
+ children: "Localized title (optional)"
529
+ }), /* @__PURE__ */ x("input", {
530
+ id: "loc-title",
531
+ type: "text",
532
+ value: G,
533
+ onChange: (e) => K(e.target.value),
534
+ placeholder: "Title in this language",
535
+ className: D
536
+ })] }), /* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("label", {
537
+ htmlFor: "loc-synopsis",
538
+ className: O,
539
+ children: "Localized synopsis (optional)"
540
+ }), /* @__PURE__ */ x("input", {
541
+ id: "loc-synopsis",
542
+ type: "text",
543
+ value: Oe,
544
+ onChange: (e) => ke(e.target.value),
545
+ placeholder: "Short synopsis in this language",
546
+ className: D
547
+ })] })]
548
+ }),
549
+ /* @__PURE__ */ S("label", {
550
+ className: "flex items-center gap-2 text-sm text-text-primary",
551
+ children: [
552
+ /* @__PURE__ */ x("input", {
553
+ type: "checkbox",
554
+ checked: Ae,
555
+ onChange: (e) => je(e.target.checked),
556
+ className: "h-4 w-4 rounded border-border-subtle"
557
+ }),
558
+ "Make this the default ",
559
+ $.label.toLowerCase(),
560
+ " track"
561
+ ]
562
+ }),
563
+ Pe && /* @__PURE__ */ x("p", {
564
+ className: "text-xs text-status-error-text",
565
+ children: Pe
566
+ }),
567
+ /* @__PURE__ */ S("div", {
568
+ className: "flex items-center gap-3",
569
+ children: [/* @__PURE__ */ x("button", {
570
+ type: "submit",
571
+ disabled: Me,
572
+ 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",
573
+ children: Me ? /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ x(g, {
574
+ className: "h-4 w-4 animate-spin",
575
+ "aria-hidden": "true"
576
+ }), "Uploading…"] }) : /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ x(me, {
577
+ className: "h-4 w-4",
578
+ "aria-hidden": "true"
579
+ }), "Add track"] })
580
+ }), /* @__PURE__ */ x("button", {
581
+ type: "button",
582
+ onClick: () => {
583
+ We(), z(!1);
584
+ },
585
+ className: "rounded-lg border border-border-seam px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
586
+ children: "Cancel"
587
+ })]
588
+ })
589
+ ]
590
+ }),
591
+ Y && /* @__PURE__ */ x("div", {
592
+ 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",
593
+ children: Y
594
+ }),
595
+ M.isLoading ? /* @__PURE__ */ x(d, {
596
+ label: "Loading tracks…",
597
+ className: "min-h-[24vh]"
598
+ }) : M.isError ? /* @__PURE__ */ x(oe, {
599
+ title: "Could not load tracks",
600
+ message: "Something went wrong fetching this title's localization tracks.",
601
+ onRetry: () => void M.refetch(),
602
+ className: "min-h-[24vh]"
603
+ }) : Z.length === 0 ? /* @__PURE__ */ x(ae, {
604
+ icon: /* @__PURE__ */ x(p, { className: "h-12 w-12" }),
605
+ title: "No localization tracks yet",
606
+ description: "Add a subtitle, caption or dub track to make this title accessible in more languages."
607
+ }) : /* @__PURE__ */ x("div", {
608
+ className: "overflow-x-auto",
609
+ children: /* @__PURE__ */ S("table", {
610
+ className: "w-full min-w-[640px] border-collapse text-left",
611
+ children: [/* @__PURE__ */ x("thead", { children: /* @__PURE__ */ S("tr", {
612
+ className: "text-xs uppercase tracking-wide text-text-secondary",
613
+ children: [
614
+ /* @__PURE__ */ x("th", {
615
+ className: "px-4 py-2 font-medium",
616
+ children: "Language"
617
+ }),
618
+ /* @__PURE__ */ x("th", {
619
+ className: "px-4 py-2 font-medium",
620
+ children: "Type"
621
+ }),
622
+ /* @__PURE__ */ x("th", {
623
+ className: "px-4 py-2 font-medium",
624
+ children: "Status"
625
+ }),
626
+ /* @__PURE__ */ x("th", {
627
+ className: "px-4 py-2 font-medium",
628
+ children: "Default"
629
+ }),
630
+ /* @__PURE__ */ x("th", {
631
+ className: "px-4 py-2 font-medium",
632
+ children: "File"
633
+ }),
634
+ /* @__PURE__ */ x("th", {
635
+ className: "px-4 py-2 text-right font-medium",
636
+ children: "Actions"
637
+ })
638
+ ]
639
+ }) }), /* @__PURE__ */ x("tbody", { children: Z.map((e) => /* @__PURE__ */ x(ye, {
640
+ track: e,
641
+ onSetDefault: (e) => void qe(e),
642
+ onDelete: (e) => void Je(e),
643
+ settingDefault: Fe === e.id,
644
+ deleting: Le === e.id
645
+ }, e.id)) })]
646
+ })
647
+ })
648
+ ]
649
+ })
650
+ ]
651
+ });
652
+ };
653
+ //#endregion
654
+ export { k as LocalizationPage };
655
+
656
+ //# sourceMappingURL=LocalizationPage.js.map