@burdenoff/microfe-hookmovies 2026.706.3 → 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.
- package/dist/hookmovies/pages/HomePage.js +211 -139
- package/dist/hookmovies/pages/HomePage.js.map +1 -1
- package/dist/hookmovies/pages/ai/ConciergePage.js +3 -3
- package/dist/hookmovies/pages/auditions/AuditionDetailPage.js +223 -140
- package/dist/hookmovies/pages/auditions/AuditionDetailPage.js.map +1 -1
- package/dist/hookmovies/pages/auditions/AuditionsPage.js +159 -81
- package/dist/hookmovies/pages/auditions/AuditionsPage.js.map +1 -1
- package/dist/hookmovies/pages/catalog/PeoplePage.js +175 -101
- package/dist/hookmovies/pages/catalog/PeoplePage.js.map +1 -1
- package/dist/hookmovies/pages/catalog/StudiosPage.js +189 -106
- package/dist/hookmovies/pages/catalog/StudiosPage.js.map +1 -1
- package/dist/hookmovies/pages/catalog/TitleDetailPage.js +745 -623
- package/dist/hookmovies/pages/catalog/TitleDetailPage.js.map +1 -1
- package/dist/hookmovies/pages/catalog/TitlesPage.js +218 -138
- package/dist/hookmovies/pages/catalog/TitlesPage.js.map +1 -1
- package/dist/hookmovies/pages/commerce/CheckoutPage.js +8 -8
- package/dist/hookmovies/pages/consumer/DiscoveryPage.js +14 -14
- package/dist/hookmovies/pages/consumer/TitleViewPage.js +6 -6
- package/dist/hookmovies/pages/distribution/RightsWindowsPage.js +235 -162
- package/dist/hookmovies/pages/distribution/RightsWindowsPage.js.map +1 -1
- package/dist/hookmovies/pages/library/EntitlementsPage.js +447 -221
- package/dist/hookmovies/pages/library/EntitlementsPage.js.map +1 -1
- package/dist/hookmovies/pages/library/ListsPage.js +242 -166
- package/dist/hookmovies/pages/library/ListsPage.js.map +1 -1
- package/dist/hookmovies/pages/live/LivePage.js +12 -12
- package/dist/hookmovies/pages/localization/LocalizationPage.js +10 -10
- package/dist/hookmovies/pages/productions/ProductionDetailPage.js +265 -179
- package/dist/hookmovies/pages/productions/ProductionDetailPage.js.map +1 -1
- package/dist/hookmovies/pages/productions/ProductionsPage.js +264 -71
- package/dist/hookmovies/pages/productions/ProductionsPage.js.map +1 -1
- package/dist/hookmovies/pages/social/WatchPartyRoomPage.js +205 -205
- package/dist/hookmovies/pages/social/WatchPartyRoomPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuditionDetailPage.js","names":[],"sources":["../../../../src/hookmovies/pages/auditions/AuditionDetailPage.tsx"],"sourcesContent":["/**\n * Audition detail (Casting marketplace)\n * @module hookmovies/pages/auditions\n *\n * Two-sided surface:\n * - Talent can apply via `hokApplyToAudition` (self-scoped).\n * - Casting teams screen applicants from `hokListApplications`, score them via\n * `hokScoreApplication`, and close the call with `hokCloseAudition`.\n */\n\nimport { type ChangeEvent, type FC, type FormEvent, useRef, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n MapPin,\n Languages,\n Clock,\n Coins,\n Send,\n Lock,\n Users,\n Upload,\n Film,\n Loader2,\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 { useHookMovies } from '../../context/HookMoviesContext';\nimport {\n useAuditionById,\n useAuditionApplications,\n useApplyToAudition,\n useScoreApplication,\n useCloseAudition,\n} from '../../hooks/useHookMoviesApi';\nimport { uploadFileToFiles, FILE_FOLDERS } from '../../hooks/useFiles';\nimport { formatDate, formatMinorUnits, formatRelativeTime } from '../../utils/formatters';\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)]';\n\nexport const AuditionDetailPage: FC = () => {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useHookMovies();\n const { data: audition, isLoading, isError, refetch } = useAuditionById(id);\n const applications = useAuditionApplications(id);\n const apply = useApplyToAudition();\n const score = useScoreApplication();\n const closeAudition = useCloseAudition();\n\n const [coverNote, setCoverNote] = useState('');\n const [selfTapeFileId, setSelfTapeFileId] = useState('');\n const [selfTapeName, setSelfTapeName] = useState('');\n const [uploading, setUploading] = useState(false);\n const [uploadError, setUploadError] = useState<string | null>(null);\n const [applyError, setApplyError] = useState<string | null>(null);\n const [applied, setApplied] = useState(false);\n const [scoreError, setScoreError] = useState<string | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n if (isLoading) {\n return (\n <PageLayout title=\"Audition\">\n <LoadingState label=\"Loading audition…\" />\n </PageLayout>\n );\n }\n\n if (isError || !audition) {\n return (\n <PageLayout title=\"Audition\">\n <ErrorState title=\"Audition not found\" onRetry={() => void refetch()} />\n </PageLayout>\n );\n }\n\n const handleApply = async (e: FormEvent) => {\n e.preventDefault();\n setApplyError(null);\n try {\n await apply.mutateAsync({\n auditionId: audition.id,\n coverNote: coverNote.trim() || undefined,\n selfTapeFileId: selfTapeFileId.trim() || undefined,\n });\n setApplied(true);\n setCoverNote('');\n setSelfTapeFileId('');\n setSelfTapeName('');\n } catch (err) {\n setApplyError(err instanceof Error ? err.message : 'Failed to apply');\n }\n };\n\n const handleSelfTapeChange = async (e: ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n // Reset the input so re-selecting the same file re-triggers change.\n e.target.value = '';\n if (!file) return;\n setUploadError(null);\n setUploading(true);\n try {\n const uploaded = await uploadFileToFiles(file, FILE_FOLDERS.selfTapes);\n setSelfTapeFileId(uploaded.id);\n setSelfTapeName(uploaded.name || file.name);\n } catch (err) {\n setUploadError(err instanceof Error ? err.message : 'Failed to upload self-tape');\n } finally {\n setUploading(false);\n }\n };\n\n const clearSelfTape = () => {\n setSelfTapeFileId('');\n setSelfTapeName('');\n setUploadError(null);\n };\n\n const handleScore = async (applicationId: string, value: number) => {\n setScoreError(null);\n try {\n await score.mutateAsync({ id: applicationId, score: value });\n } catch (err) {\n setScoreError(err instanceof Error ? err.message : 'Failed to score');\n }\n };\n\n const isOpen = audition.status === 'OPEN';\n const applicationItems = applications.data ?? [];\n\n return (\n <PageLayout\n title={\n <span className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigateTo('auditions')}\n className=\"rounded-md p-1 text-text-secondary hover:text-text-primary\"\n aria-label=\"Back to auditions\"\n >\n <ArrowLeft className=\"h-5 w-5\" />\n </button>\n {audition.roleName}\n </span>\n }\n description={audition.production?.title ?? 'Casting call'}\n actions={\n <div className=\"flex items-center gap-2\">\n <StatusBadge status={audition.status} />\n {isOpen && (\n <button\n type=\"button\"\n disabled={closeAudition.isPending}\n onClick={() => void closeAudition.mutateAsync(audition.id)}\n className=\"inline-flex items-center gap-1 rounded-lg border border-border-seam px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken disabled:opacity-50 transition-colors\"\n >\n <Lock className=\"h-3.5 w-3.5\" />\n Close\n </button>\n )}\n </div>\n }\n >\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n <div className=\"space-y-6 lg:col-span-2\">\n {audition.description && (\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-2 text-sm font-semibold text-text-primary\">Role Description</h2>\n <p className=\"text-sm leading-relaxed text-text-secondary\">{audition.description}</p>\n </GlassCard>\n )}\n\n {/* Applicants (casting view) */}\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 Applicants ({applicationItems.length})\n </h2>\n {scoreError && (\n <div className=\"mb-3 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-xs text-status-error-text\">\n {scoreError}\n </div>\n )}\n {applications.isLoading ? (\n <LoadingState label=\"Loading applicants…\" className=\"min-h-[120px]\" />\n ) : applicationItems.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">No applications yet.</p>\n ) : (\n <ul className=\"space-y-3\">\n {applicationItems.map((appn) => (\n <li\n key={appn.id}\n className=\"rounded-lg border border-border-seam bg-bg-surface p-3\"\n >\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-medium text-text-primary\">\n Applicant {appn.applicantId.slice(0, 8)}\n </p>\n <p className=\"text-xs text-text-secondary\">\n Applied {formatRelativeTime(appn.createdAt)}\n </p>\n </div>\n <StatusBadge status={appn.status} />\n </div>\n {appn.coverNote && (\n <p className=\"mt-2 text-sm text-text-secondary\">{appn.coverNote}</p>\n )}\n <div className=\"mt-3 flex items-center gap-2\">\n <span className=\"text-xs text-text-secondary\">Score:</span>\n {[1, 2, 3, 4, 5].map((value) => (\n <button\n key={value}\n type=\"button\"\n disabled={score.isPending}\n onClick={() => void handleScore(appn.id, value)}\n className={\n appn.score === value\n ? 'h-7 w-7 rounded-md bg-action-primary-bg text-xs font-semibold text-action-primary-text'\n : 'h-7 w-7 rounded-md border border-border-seam text-xs text-text-primary hover:bg-bg-sunken transition-colors'\n }\n >\n {value}\n </button>\n ))}\n </div>\n </li>\n ))}\n </ul>\n )}\n </GlassCard>\n </div>\n\n <div className=\"space-y-6\">\n {/* Details */}\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 text-sm\">\n <div className=\"flex items-center justify-between\">\n <dt className=\"flex items-center gap-2 text-text-secondary\">\n <Coins className=\"h-3.5 w-3.5\" />\n Pay\n </dt>\n <dd className=\"font-medium text-text-primary\">\n {formatMinorUnits(audition.payMinorUnits, audition.currency)}\n </dd>\n </div>\n {audition.location && (\n <div className=\"flex items-center justify-between\">\n <dt className=\"flex items-center gap-2 text-text-secondary\">\n <MapPin className=\"h-3.5 w-3.5\" />\n Location\n </dt>\n <dd className=\"font-medium text-text-primary\">{audition.location}</dd>\n </div>\n )}\n {audition.language && (\n <div className=\"flex items-center justify-between\">\n <dt className=\"flex items-center gap-2 text-text-secondary\">\n <Languages className=\"h-3.5 w-3.5\" />\n Language\n </dt>\n <dd className=\"font-medium text-text-primary\">{audition.language}</dd>\n </div>\n )}\n {audition.submissionDeadline && (\n <div className=\"flex items-center justify-between\">\n <dt className=\"flex items-center gap-2 text-text-secondary\">\n <Clock className=\"h-3.5 w-3.5\" />\n Deadline\n </dt>\n <dd className=\"font-medium text-text-primary\">\n {formatDate(audition.submissionDeadline, {\n hour: undefined,\n minute: undefined,\n })}\n </dd>\n </div>\n )}\n </dl>\n {audition.isMinorRole && (\n <p className=\"mt-3 rounded-lg bg-status-warning-bg-subtle px-3 py-2 text-xs text-status-warning-text\">\n This is a minor role. Guardian consent and restricted communications apply.\n </p>\n )}\n </GlassCard>\n\n {/* Apply (talent view) */}\n <GlassCard treatment=\"glass\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-3 text-sm font-semibold text-text-primary\">Apply</h2>\n {applied ? (\n <p className=\"rounded-lg bg-status-success-bg-subtle px-3 py-2 text-sm text-status-success-text\">\n Your application has been submitted.\n </p>\n ) : !isOpen ? (\n <p className=\"text-sm text-text-secondary\">This audition is no longer open.</p>\n ) : (\n <form onSubmit={handleApply} className=\"space-y-3\">\n {applyError && (\n <div className=\"rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-xs text-status-error-text\">\n {applyError}\n </div>\n )}\n <textarea\n value={coverNote}\n onChange={(e) => setCoverNote(e.target.value)}\n rows={3}\n placeholder=\"Cover note (why you're right for this role)\"\n className={fieldClass}\n />\n <div className=\"space-y-2\">\n <label\n htmlFor=\"self-tape-upload\"\n className=\"block text-xs font-medium text-text-secondary\"\n >\n Self-tape (optional)\n </label>\n <input\n ref={fileInputRef}\n id=\"self-tape-upload\"\n type=\"file\"\n accept=\"video/*\"\n onChange={(e) => void handleSelfTapeChange(e)}\n disabled={uploading}\n className=\"sr-only\"\n aria-label=\"Upload self-tape video\"\n />\n {selfTapeFileId ? (\n <div className=\"flex items-center justify-between gap-2 rounded-lg border border-border-seam bg-bg-surface px-3 py-2\">\n <span className=\"flex min-w-0 items-center gap-2 text-sm text-text-primary\">\n <Film className=\"h-4 w-4 shrink-0 text-status-success-text\" />\n <span className=\"truncate\">{selfTapeName || 'Self-tape uploaded'}</span>\n </span>\n <button\n type=\"button\"\n onClick={clearSelfTape}\n className=\"rounded-md p-1 text-text-secondary hover:text-text-primary\"\n aria-label=\"Remove self-tape\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n disabled={uploading}\n className=\"inline-flex w-full items-center justify-center gap-2 rounded-lg border border-dashed border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-secondary hover:border-border-seam hover:text-text-primary disabled:opacity-50 transition-colors\"\n >\n {uploading ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n Uploading…\n </>\n ) : (\n <>\n <Upload className=\"h-4 w-4\" />\n Upload self-tape video\n </>\n )}\n </button>\n )}\n {uploadError && (\n <p className=\"rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-xs text-status-error-text\">\n {uploadError}\n </p>\n )}\n </div>\n <button\n type=\"submit\"\n disabled={apply.isPending || uploading}\n className=\"inline-flex w-full items-center justify-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 <Send className=\"h-4 w-4\" />\n {apply.isPending ? 'Submitting…' : 'Submit Application'}\n </button>\n </form>\n )}\n </GlassCard>\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AuditionDetailPage.js","names":[],"sources":["../../../../src/hookmovies/pages/auditions/AuditionDetailPage.tsx"],"sourcesContent":["/**\n * Audition detail (Casting marketplace)\n * @module hookmovies/pages/auditions\n *\n * Two-sided surface:\n * - Talent can apply via `hokApplyToAudition` (self-scoped).\n * - Casting teams screen applicants from `hokListApplications`, score them via\n * `hokScoreApplication`, and close the call with `hokCloseAudition`.\n */\n\nimport { type ChangeEvent, type FC, type FormEvent, useMemo, useRef, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n MapPin,\n Languages,\n Clock,\n Coins,\n Send,\n Lock,\n Users,\n Upload,\n Film,\n Loader2,\n Star,\n ShieldAlert,\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 { useHookMovies } from '../../context/HookMoviesContext';\nimport {\n type HokApplication,\n useAuditionById,\n useAuditionApplications,\n useApplyToAudition,\n useScoreApplication,\n useCloseAudition,\n} from '../../hooks/useHookMoviesApi';\nimport { uploadFileToFiles, FILE_FOLDERS } from '../../hooks/useFiles';\nimport { formatDate, formatMinorUnits, formatRelativeTime } from '../../utils/formatters';\nimport { cn } from '../../utils/cn';\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)]';\n\n/** Short, deterministic label for an anonymised applicant avatar. */\nfunction applicantInitials(applicantId: string): string {\n const cleaned = applicantId.replace(/[^a-zA-Z0-9]/g, '');\n return (cleaned.slice(0, 2) || '?').toUpperCase();\n}\n\n/** Statuses that represent a positive casting outcome — highlighted in the list. */\nconst HIGHLIGHT_STATUSES = new Set(['shortlisted', 'callback', 'offered']);\n\ninterface ScoreStarsProps {\n value: number | null;\n disabled: boolean;\n onScore: (value: number) => void;\n}\n\n/** Accessible 1–5 star rating control wired to `hokScoreApplication`. */\nconst ScoreStars: FC<ScoreStarsProps> = ({ value, disabled, onScore }) => (\n <div\n className=\"flex items-center gap-1\"\n role=\"group\"\n aria-label={value ? `Rating ${value} of 5` : 'Not yet rated'}\n >\n {[1, 2, 3, 4, 5].map((star) => {\n const active = value !== null && star <= value;\n return (\n <button\n key={star}\n type=\"button\"\n disabled={disabled}\n onClick={() => onScore(star)}\n aria-label={`Score ${star} of 5`}\n aria-pressed={value === star}\n title={`Score ${star} of 5`}\n className=\"rounded p-0.5 text-text-muted transition-colors hover:text-status-warning-text focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] disabled:cursor-not-allowed disabled:opacity-60\"\n >\n <Star\n className={cn(\n 'h-5 w-5 transition-transform',\n active ? 'fill-status-warning-text text-status-warning-text' : 'fill-transparent'\n )}\n />\n </button>\n );\n })}\n </div>\n);\n\nexport const AuditionDetailPage: FC = () => {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useHookMovies();\n const { data: audition, isLoading, isError, refetch } = useAuditionById(id);\n const applications = useAuditionApplications(id);\n const apply = useApplyToAudition();\n const score = useScoreApplication();\n const closeAudition = useCloseAudition();\n\n const [coverNote, setCoverNote] = useState('');\n const [selfTapeFileId, setSelfTapeFileId] = useState('');\n const [selfTapeName, setSelfTapeName] = useState('');\n const [uploading, setUploading] = useState(false);\n const [uploadError, setUploadError] = useState<string | null>(null);\n const [applyError, setApplyError] = useState<string | null>(null);\n const [applied, setApplied] = useState(false);\n const [scoreError, setScoreError] = useState<string | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n const applicationItems: HokApplication[] = useMemo(\n () => applications.data ?? [],\n [applications.data]\n );\n const ratedCount = useMemo(\n () => applicationItems.filter((appn) => appn.score !== null).length,\n [applicationItems]\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"Audition\">\n <LoadingState label=\"Loading audition…\" />\n </PageLayout>\n );\n }\n\n if (isError || !audition) {\n return (\n <PageLayout title=\"Audition\">\n <ErrorState title=\"Audition not found\" onRetry={() => void refetch()} />\n </PageLayout>\n );\n }\n\n const handleApply = async (e: FormEvent) => {\n e.preventDefault();\n setApplyError(null);\n try {\n await apply.mutateAsync({\n auditionId: audition.id,\n coverNote: coverNote.trim() || undefined,\n selfTapeFileId: selfTapeFileId.trim() || undefined,\n });\n setApplied(true);\n setCoverNote('');\n setSelfTapeFileId('');\n setSelfTapeName('');\n } catch (err) {\n setApplyError(err instanceof Error ? err.message : 'Failed to apply');\n }\n };\n\n const handleSelfTapeChange = async (e: ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n // Reset the input so re-selecting the same file re-triggers change.\n e.target.value = '';\n if (!file) return;\n setUploadError(null);\n setUploading(true);\n try {\n const uploaded = await uploadFileToFiles(file, FILE_FOLDERS.selfTapes);\n setSelfTapeFileId(uploaded.id);\n setSelfTapeName(uploaded.name || file.name);\n } catch (err) {\n setUploadError(err instanceof Error ? err.message : 'Failed to upload self-tape');\n } finally {\n setUploading(false);\n }\n };\n\n const clearSelfTape = () => {\n setSelfTapeFileId('');\n setSelfTapeName('');\n setUploadError(null);\n };\n\n const handleScore = async (applicationId: string, value: number) => {\n setScoreError(null);\n try {\n await score.mutateAsync({ id: applicationId, score: value });\n } catch (err) {\n setScoreError(err instanceof Error ? err.message : 'Failed to score');\n }\n };\n\n const isOpen = audition.status === 'OPEN';\n\n return (\n <PageLayout\n hero\n title={\n <span className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigateTo('auditions')}\n className=\"rounded-md p-1 text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n aria-label=\"Back to auditions\"\n >\n <ArrowLeft className=\"h-5 w-5\" />\n </button>\n {audition.roleName}\n </span>\n }\n description={audition.production?.title ?? 'Casting call'}\n actions={\n <div className=\"flex items-center gap-2\">\n <StatusBadge status={audition.status} />\n {isOpen && (\n <button\n type=\"button\"\n disabled={closeAudition.isPending}\n onClick={() => void closeAudition.mutateAsync(audition.id)}\n className=\"inline-flex items-center gap-1.5 rounded-lg border border-border-seam px-3 py-1.5 text-xs font-medium text-text-primary transition-colors hover:bg-bg-sunken disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <Lock className=\"h-3.5 w-3.5\" />\n Close\n </button>\n )}\n </div>\n }\n >\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* ---- Applicants (casting view) — primary column ---- */}\n <div className=\"space-y-6 lg:col-span-2\">\n {audition.description && (\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-2 text-sm font-semibold text-text-primary\">Role Description</h2>\n <p className=\"text-sm leading-relaxed text-text-secondary\">{audition.description}</p>\n </GlassCard>\n )}\n\n <GlassCard treatment=\"metric\" className=\"border-border-seam p-5\">\n <div className=\"mb-4 flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Users className=\"h-4 w-4 text-text-secondary\" />\n Applicants\n <span className=\"rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {applicationItems.length}\n </span>\n </h2>\n {applicationItems.length > 0 && (\n <span className=\"flex items-center gap-1.5 text-xs text-text-secondary\">\n <Star className=\"h-3.5 w-3.5 fill-status-warning-text text-status-warning-text\" />\n {ratedCount} of {applicationItems.length} rated\n </span>\n )}\n </div>\n\n {scoreError && (\n <div className=\"mb-3 rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-xs text-status-error-text\">\n {scoreError}\n </div>\n )}\n\n {applications.isLoading ? (\n <LoadingState label=\"Loading applicants…\" className=\"min-h-[160px]\" />\n ) : applicationItems.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed border-border-seam bg-bg-surface/60 px-4 py-12 text-center\">\n <div className=\"flex h-11 w-11 items-center justify-center rounded-full bg-bg-sunken\">\n <Users className=\"h-5 w-5 text-text-muted\" />\n </div>\n <p className=\"text-sm font-medium text-text-primary\">No applications yet</p>\n <p className=\"max-w-xs text-xs text-text-secondary\">\n Applicants who apply to this role will appear here for review and scoring.\n </p>\n </div>\n ) : (\n <ul className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {applicationItems.map((appn) => {\n const highlighted = HIGHLIGHT_STATUSES.has(appn.status.toLowerCase());\n return (\n <li\n key={appn.id}\n className={cn(\n 'flex flex-col rounded-xl border bg-bg-surface p-4 transition-colors',\n highlighted\n ? 'border-status-info-border ring-1 ring-status-info-border'\n : 'border-border-seam hover:border-border-strong'\n )}\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex min-w-0 items-center gap-3\">\n <span\n className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-full border border-border-seam bg-bg-sunken text-xs font-semibold text-text-secondary\"\n aria-hidden=\"true\"\n >\n {applicantInitials(appn.applicantId)}\n </span>\n <div className=\"min-w-0\">\n <p className=\"truncate text-sm font-semibold text-text-primary\">\n Applicant {appn.applicantId.slice(0, 8)}\n </p>\n <p className=\"text-xs text-text-secondary\">\n Applied {formatRelativeTime(appn.createdAt)}\n </p>\n </div>\n </div>\n <StatusBadge status={appn.status} className=\"shrink-0\" />\n </div>\n\n {appn.coverNote ? (\n <p className=\"mt-3 line-clamp-3 text-sm leading-relaxed text-text-secondary\">\n <span className=\"text-text-muted\">“</span>\n {appn.coverNote}\n <span className=\"text-text-muted\">”</span>\n </p>\n ) : (\n <p className=\"mt-3 text-sm italic text-text-muted\">\n No cover note provided.\n </p>\n )}\n\n <div className=\"mt-auto flex items-center justify-between gap-2 pt-4\">\n <ScoreStars\n value={appn.score}\n disabled={score.isPending}\n onScore={(value) => void handleScore(appn.id, value)}\n />\n <span className=\"text-xs font-medium text-text-secondary\">\n {appn.score !== null ? `${appn.score}/5` : 'Unrated'}\n </span>\n </div>\n </li>\n );\n })}\n </ul>\n )}\n </GlassCard>\n </div>\n\n {/* ---- Details + Apply — secondary column ---- */}\n <div className=\"space-y-6\">\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-3 text-sm\">\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"flex items-center gap-2 text-text-secondary\">\n <Coins className=\"h-3.5 w-3.5\" />\n Pay\n </dt>\n <dd className=\"text-right font-medium text-text-primary\">\n {formatMinorUnits(audition.payMinorUnits, audition.currency)}\n </dd>\n </div>\n {audition.location && (\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"flex items-center gap-2 text-text-secondary\">\n <MapPin className=\"h-3.5 w-3.5\" />\n Location\n </dt>\n <dd className=\"text-right font-medium text-text-primary\">{audition.location}</dd>\n </div>\n )}\n {audition.language && (\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"flex items-center gap-2 text-text-secondary\">\n <Languages className=\"h-3.5 w-3.5\" />\n Language\n </dt>\n <dd className=\"text-right font-medium text-text-primary\">{audition.language}</dd>\n </div>\n )}\n {audition.submissionDeadline && (\n <div className=\"flex items-center justify-between gap-3\">\n <dt className=\"flex items-center gap-2 text-text-secondary\">\n <Clock className=\"h-3.5 w-3.5\" />\n Deadline\n </dt>\n <dd className=\"text-right font-medium text-text-primary\">\n {formatDate(audition.submissionDeadline, {\n hour: undefined,\n minute: undefined,\n })}\n </dd>\n </div>\n )}\n </dl>\n {audition.isMinorRole && (\n <div className=\"mt-4 flex items-start gap-2 rounded-lg border border-status-warning-border bg-status-warning-bg-subtle px-3 py-2 text-xs text-status-warning-text\">\n <ShieldAlert className=\"mt-0.5 h-4 w-4 shrink-0\" />\n <span>\n This is a minor role. Guardian consent and restricted communications apply.\n </span>\n </div>\n )}\n </GlassCard>\n\n {/* Apply (talent view) */}\n <GlassCard treatment=\"glass\" className=\"border-border-seam p-5\">\n <h2 className=\"mb-3 flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <Send className=\"h-4 w-4 text-text-secondary\" />\n Apply for this role\n </h2>\n {applied ? (\n <div className=\"rounded-lg border border-status-success-border bg-status-success-bg-subtle px-3 py-2.5 text-sm text-status-success-text\">\n Your application has been submitted.\n </div>\n ) : !isOpen ? (\n <p className=\"rounded-lg bg-bg-sunken px-3 py-2.5 text-sm text-text-secondary\">\n This audition is no longer open for applications.\n </p>\n ) : (\n <form onSubmit={handleApply} className=\"space-y-3\">\n {applyError && (\n <div className=\"rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-xs text-status-error-text\">\n {applyError}\n </div>\n )}\n <div className=\"space-y-1.5\">\n <label\n htmlFor=\"cover-note\"\n className=\"block text-xs font-medium text-text-secondary\"\n >\n Cover note\n </label>\n <textarea\n id=\"cover-note\"\n value={coverNote}\n onChange={(e) => setCoverNote(e.target.value)}\n rows={3}\n placeholder=\"Why you're right for this role\"\n className={fieldClass}\n />\n </div>\n <div className=\"space-y-1.5\">\n <label\n htmlFor=\"self-tape-upload\"\n className=\"block text-xs font-medium text-text-secondary\"\n >\n Self-tape (optional)\n </label>\n <input\n ref={fileInputRef}\n id=\"self-tape-upload\"\n type=\"file\"\n accept=\"video/*\"\n onChange={(e) => void handleSelfTapeChange(e)}\n disabled={uploading}\n className=\"sr-only\"\n aria-label=\"Upload self-tape video\"\n />\n {selfTapeFileId ? (\n <div className=\"flex items-center justify-between gap-2 rounded-lg border border-border-seam bg-bg-surface px-3 py-2\">\n <span className=\"flex min-w-0 items-center gap-2 text-sm text-text-primary\">\n <Film className=\"h-4 w-4 shrink-0 text-status-success-text\" />\n <span className=\"truncate\">{selfTapeName || 'Self-tape uploaded'}</span>\n </span>\n <button\n type=\"button\"\n onClick={clearSelfTape}\n className=\"rounded-md p-1 text-text-secondary transition-colors hover:text-text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n aria-label=\"Remove self-tape\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n disabled={uploading}\n className=\"inline-flex w-full items-center justify-center gap-2 rounded-lg border border-dashed border-border-subtle bg-bg-surface px-3 py-3 text-sm text-text-secondary transition-colors hover:border-border-seam hover:text-text-primary disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n {uploading ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n Uploading…\n </>\n ) : (\n <>\n <Upload className=\"h-4 w-4\" />\n Upload self-tape video\n </>\n )}\n </button>\n )}\n {uploadError && (\n <p className=\"rounded-lg border border-status-error-border bg-status-error-bg-subtle px-3 py-2 text-xs text-status-error-text\">\n {uploadError}\n </p>\n )}\n </div>\n <button\n type=\"submit\"\n disabled={apply.isPending || uploading}\n className=\"inline-flex w-full items-center justify-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2.5 text-sm font-medium text-action-primary-text transition-opacity hover:opacity-90 disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <Send className=\"h-4 w-4\" />\n {apply.isPending ? 'Submitting…' : 'Submit Application'}\n </button>\n </form>\n )}\n </GlassCard>\n </div>\n </div>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -7,131 +7,209 @@ import { EmptyState as s } from "../../components/EmptyState.js";
|
|
|
7
7
|
import { ErrorState as c, LoadingState as l } from "../../components/StateViews.js";
|
|
8
8
|
import { Pagination as u } from "../../components/Pagination.js";
|
|
9
9
|
import { useState as d } from "react";
|
|
10
|
-
import {
|
|
11
|
-
import { jsx as
|
|
12
|
-
import { GlassCard as
|
|
10
|
+
import { ArrowUpRight as f, Banknote as p, Clock as m, Film as h, Languages as g, MapPin as _, Megaphone as v, Plus as y, ShieldAlert as b } from "lucide-react";
|
|
11
|
+
import { jsx as x, jsxs as S } from "react/jsx-runtime";
|
|
12
|
+
import { GlassCard as C } from "@burdenoff/fe-libs/ui";
|
|
13
13
|
//#region src/hookmovies/pages/auditions/AuditionsPage.tsx
|
|
14
|
-
var
|
|
14
|
+
var w = [{
|
|
15
|
+
value: "",
|
|
16
|
+
label: "Any Status"
|
|
17
|
+
}, ...[
|
|
15
18
|
"OPEN",
|
|
16
19
|
"REVIEWING",
|
|
17
20
|
"CALLBACKS",
|
|
18
21
|
"CLOSED",
|
|
19
22
|
"CANCELLED"
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}), j =
|
|
25
|
-
|
|
23
|
+
].map((e) => ({
|
|
24
|
+
value: e,
|
|
25
|
+
label: a(e)
|
|
26
|
+
}))], T = 20, E = () => {
|
|
27
|
+
let { navigateTo: a } = e(), [E, D] = d("OPEN"), [O, k] = d(0), { data: A, isLoading: j, isError: M, refetch: N } = r({ status: E || void 0 }, {
|
|
28
|
+
limit: T,
|
|
29
|
+
offset: O * T
|
|
30
|
+
}), P = A?.items ?? [], F = (e) => {
|
|
31
|
+
D(e), k(0);
|
|
32
|
+
};
|
|
33
|
+
return /* @__PURE__ */ S(t, {
|
|
26
34
|
title: "Auditions",
|
|
27
35
|
description: "Casting & talent marketplace",
|
|
28
36
|
purpose: "Open casting calls across the network. Talent discover and apply to roles with a self-tape; casting teams screen, score, and shortlist applicants.",
|
|
29
|
-
actions: /* @__PURE__ */
|
|
37
|
+
actions: /* @__PURE__ */ S("button", {
|
|
30
38
|
type: "button",
|
|
31
|
-
onClick: () =>
|
|
32
|
-
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",
|
|
33
|
-
children: [/* @__PURE__ */
|
|
39
|
+
onClick: () => a("auditions/new"),
|
|
40
|
+
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 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] transition-opacity",
|
|
41
|
+
children: [/* @__PURE__ */ x(y, {
|
|
42
|
+
className: "h-4 w-4",
|
|
43
|
+
"aria-hidden": "true"
|
|
44
|
+
}), "Post Role"]
|
|
34
45
|
}),
|
|
35
46
|
children: [
|
|
36
|
-
/* @__PURE__ */
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
children: a(e)
|
|
50
|
-
}, e))]
|
|
47
|
+
/* @__PURE__ */ x("div", {
|
|
48
|
+
role: "group",
|
|
49
|
+
"aria-label": "Filter auditions by status",
|
|
50
|
+
className: "mb-5 -mx-1 flex items-center gap-2 overflow-x-auto px-1 pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
51
|
+
children: w.map((e) => {
|
|
52
|
+
let t = E === e.value;
|
|
53
|
+
return /* @__PURE__ */ x("button", {
|
|
54
|
+
type: "button",
|
|
55
|
+
"aria-pressed": t,
|
|
56
|
+
onClick: () => F(e.value),
|
|
57
|
+
className: `shrink-0 whitespace-nowrap rounded-full border px-3.5 py-1.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] ${t ? "border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg" : "border-border-subtle text-text-secondary hover:border-border-strong hover:text-text-primary"}`,
|
|
58
|
+
children: e.label
|
|
59
|
+
}, e.value || "any");
|
|
51
60
|
})
|
|
52
61
|
}),
|
|
53
|
-
|
|
54
|
-
icon: /* @__PURE__ */
|
|
62
|
+
j ? /* @__PURE__ */ x(l, { label: "Loading auditions…" }) : M ? /* @__PURE__ */ x(c, { onRetry: () => void N() }) : P.length === 0 ? /* @__PURE__ */ x(s, {
|
|
63
|
+
icon: /* @__PURE__ */ x(v, { className: "h-12 w-12" }),
|
|
55
64
|
title: "No auditions",
|
|
56
65
|
description: "No casting calls match this filter.",
|
|
57
|
-
action: /* @__PURE__ */
|
|
66
|
+
action: /* @__PURE__ */ x("button", {
|
|
58
67
|
type: "button",
|
|
59
|
-
onClick: () =>
|
|
60
|
-
className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 transition-opacity",
|
|
68
|
+
onClick: () => a("auditions/new"),
|
|
69
|
+
className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] transition-opacity",
|
|
61
70
|
children: "Post a Role"
|
|
62
71
|
})
|
|
63
|
-
}) : /* @__PURE__ */
|
|
64
|
-
className: "grid grid-cols-1 gap-4 sm:grid-cols-2
|
|
65
|
-
children:
|
|
72
|
+
}) : /* @__PURE__ */ x("div", {
|
|
73
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3",
|
|
74
|
+
children: P.map((e) => /* @__PURE__ */ x("button", {
|
|
66
75
|
type: "button",
|
|
67
|
-
onClick: () =>
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
onClick: () => a(`auditions/${e.id}`),
|
|
77
|
+
"aria-label": `View casting call: ${e.roleName}`,
|
|
78
|
+
className: "group text-left focus-visible:outline-none",
|
|
79
|
+
children: /* @__PURE__ */ S(C, {
|
|
70
80
|
treatment: "metric",
|
|
71
|
-
className: "flex h-full flex-col border-border-seam p-
|
|
81
|
+
className: "flex h-full flex-col border-border-seam p-5 transition-all duration-200 group-hover:-translate-y-0.5 group-hover:border-action-primary-bg/40 group-focus-visible:border-action-primary-bg/60 group-focus-visible:ring-2 group-focus-visible:ring-[var(--color-focus-ring)]",
|
|
72
82
|
children: [
|
|
73
|
-
/* @__PURE__ */
|
|
83
|
+
/* @__PURE__ */ S("div", {
|
|
74
84
|
className: "flex items-start justify-between gap-2",
|
|
75
|
-
children: [/* @__PURE__ */
|
|
76
|
-
className: "
|
|
77
|
-
children:
|
|
78
|
-
|
|
85
|
+
children: [/* @__PURE__ */ S("div", {
|
|
86
|
+
className: "min-w-0",
|
|
87
|
+
children: [/* @__PURE__ */ x("h3", {
|
|
88
|
+
className: "line-clamp-2 text-sm font-semibold text-text-primary",
|
|
89
|
+
children: e.roleName
|
|
90
|
+
}), /* @__PURE__ */ S("p", {
|
|
91
|
+
className: "mt-1 flex items-center gap-1.5 text-xs text-text-secondary",
|
|
92
|
+
children: [/* @__PURE__ */ x(h, {
|
|
93
|
+
className: "h-3 w-3 shrink-0",
|
|
94
|
+
"aria-hidden": "true"
|
|
95
|
+
}), /* @__PURE__ */ x("span", {
|
|
96
|
+
className: "truncate",
|
|
97
|
+
children: e.production?.title ?? "Unassigned production"
|
|
98
|
+
})]
|
|
99
|
+
})]
|
|
100
|
+
}), /* @__PURE__ */ x(n, {
|
|
101
|
+
status: e.status,
|
|
102
|
+
className: "shrink-0"
|
|
103
|
+
})]
|
|
79
104
|
}),
|
|
80
|
-
e.
|
|
81
|
-
className: "mt-1 text-
|
|
82
|
-
children:
|
|
105
|
+
e.isMinorRole && /* @__PURE__ */ S("span", {
|
|
106
|
+
className: "mt-3 inline-flex w-fit items-center gap-1 rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-[10px] font-medium text-status-warning-text",
|
|
107
|
+
children: [/* @__PURE__ */ x(b, {
|
|
108
|
+
className: "h-3 w-3",
|
|
109
|
+
"aria-hidden": "true"
|
|
110
|
+
}), "Minor role — guardian consent required"]
|
|
83
111
|
}),
|
|
84
|
-
e.
|
|
85
|
-
className: "mt-
|
|
86
|
-
children: "Minor role — guardian consent required"
|
|
87
|
-
}),
|
|
88
|
-
e.description && /* @__PURE__ */ _("p", {
|
|
89
|
-
className: "mt-2 line-clamp-2 text-xs text-text-secondary",
|
|
112
|
+
e.description && /* @__PURE__ */ x("p", {
|
|
113
|
+
className: "mt-3 line-clamp-2 text-xs leading-relaxed text-text-secondary",
|
|
90
114
|
children: e.description
|
|
91
115
|
}),
|
|
92
|
-
/* @__PURE__ */
|
|
93
|
-
className: "mt-
|
|
116
|
+
/* @__PURE__ */ S("div", {
|
|
117
|
+
className: "mt-4 flex items-center gap-2 rounded-lg border border-border-seam bg-bg-sunken px-3 py-2",
|
|
118
|
+
children: [/* @__PURE__ */ x(p, {
|
|
119
|
+
className: "h-4 w-4 shrink-0 text-status-success-text",
|
|
120
|
+
"aria-hidden": "true"
|
|
121
|
+
}), /* @__PURE__ */ x("span", {
|
|
122
|
+
className: "text-sm font-semibold text-text-primary",
|
|
123
|
+
children: o(e.payMinorUnits, e.currency)
|
|
124
|
+
})]
|
|
125
|
+
}),
|
|
126
|
+
/* @__PURE__ */ S("dl", {
|
|
127
|
+
className: "mt-4 grid grid-cols-1 gap-y-2 text-xs text-text-secondary",
|
|
94
128
|
children: [
|
|
95
|
-
/* @__PURE__ */
|
|
96
|
-
className: "
|
|
97
|
-
children:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
129
|
+
e.location && /* @__PURE__ */ S("div", {
|
|
130
|
+
className: "flex items-center gap-1.5",
|
|
131
|
+
children: [
|
|
132
|
+
/* @__PURE__ */ x(_, {
|
|
133
|
+
className: "h-3.5 w-3.5 shrink-0 text-text-muted",
|
|
134
|
+
"aria-hidden": "true"
|
|
135
|
+
}),
|
|
136
|
+
/* @__PURE__ */ x("dt", {
|
|
137
|
+
className: "sr-only",
|
|
138
|
+
children: "Location"
|
|
139
|
+
}),
|
|
140
|
+
/* @__PURE__ */ x("dd", {
|
|
141
|
+
className: "truncate",
|
|
142
|
+
children: e.location
|
|
143
|
+
})
|
|
144
|
+
]
|
|
102
145
|
}),
|
|
103
|
-
e.language && /* @__PURE__ */
|
|
104
|
-
className: "flex items-center gap-1",
|
|
105
|
-
children: [
|
|
146
|
+
e.language && /* @__PURE__ */ S("div", {
|
|
147
|
+
className: "flex items-center gap-1.5",
|
|
148
|
+
children: [
|
|
149
|
+
/* @__PURE__ */ x(g, {
|
|
150
|
+
className: "h-3.5 w-3.5 shrink-0 text-text-muted",
|
|
151
|
+
"aria-hidden": "true"
|
|
152
|
+
}),
|
|
153
|
+
/* @__PURE__ */ x("dt", {
|
|
154
|
+
className: "sr-only",
|
|
155
|
+
children: "Language"
|
|
156
|
+
}),
|
|
157
|
+
/* @__PURE__ */ x("dd", {
|
|
158
|
+
className: "truncate",
|
|
159
|
+
children: e.language
|
|
160
|
+
})
|
|
161
|
+
]
|
|
106
162
|
}),
|
|
107
|
-
e.submissionDeadline && /* @__PURE__ */
|
|
108
|
-
className: "flex items-center gap-1",
|
|
163
|
+
e.submissionDeadline && /* @__PURE__ */ S("div", {
|
|
164
|
+
className: "flex items-center gap-1.5",
|
|
109
165
|
children: [
|
|
110
|
-
/* @__PURE__ */
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
166
|
+
/* @__PURE__ */ x(m, {
|
|
167
|
+
className: "h-3.5 w-3.5 shrink-0 text-text-muted",
|
|
168
|
+
"aria-hidden": "true"
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ x("dt", {
|
|
171
|
+
className: "sr-only",
|
|
172
|
+
children: "Submission deadline"
|
|
173
|
+
}),
|
|
174
|
+
/* @__PURE__ */ S("dd", {
|
|
175
|
+
className: "truncate",
|
|
176
|
+
children: [
|
|
177
|
+
"Deadline",
|
|
178
|
+
" ",
|
|
179
|
+
i(e.submissionDeadline, {
|
|
180
|
+
hour: void 0,
|
|
181
|
+
minute: void 0
|
|
182
|
+
})
|
|
183
|
+
]
|
|
116
184
|
})
|
|
117
185
|
]
|
|
118
186
|
})
|
|
119
187
|
]
|
|
188
|
+
}),
|
|
189
|
+
/* @__PURE__ */ x("div", {
|
|
190
|
+
className: "mt-auto flex items-center justify-end pt-4",
|
|
191
|
+
children: /* @__PURE__ */ S("span", {
|
|
192
|
+
className: "inline-flex items-center gap-1 text-xs font-medium text-text-muted transition-colors group-hover:text-action-primary-bg",
|
|
193
|
+
children: ["View & apply", /* @__PURE__ */ x(f, {
|
|
194
|
+
className: "h-3.5 w-3.5 transition-transform group-hover:translate-x-0.5 group-hover:-translate-y-0.5",
|
|
195
|
+
"aria-hidden": "true"
|
|
196
|
+
})]
|
|
197
|
+
})
|
|
120
198
|
})
|
|
121
199
|
]
|
|
122
200
|
})
|
|
123
201
|
}, e.id))
|
|
124
202
|
}),
|
|
125
|
-
!
|
|
126
|
-
page:
|
|
127
|
-
hasMore:
|
|
128
|
-
onPageChange:
|
|
129
|
-
shownCount:
|
|
203
|
+
!j && !M && /* @__PURE__ */ x(u, {
|
|
204
|
+
page: O,
|
|
205
|
+
hasMore: A?.pageInfo.hasMore ?? !1,
|
|
206
|
+
onPageChange: k,
|
|
207
|
+
shownCount: P.length
|
|
130
208
|
})
|
|
131
209
|
]
|
|
132
210
|
});
|
|
133
211
|
};
|
|
134
212
|
//#endregion
|
|
135
|
-
export {
|
|
213
|
+
export { E as AuditionsPage };
|
|
136
214
|
|
|
137
215
|
//# sourceMappingURL=AuditionsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuditionsPage.js","names":[],"sources":["../../../../src/hookmovies/pages/auditions/AuditionsPage.tsx"],"sourcesContent":["/**\n * Auditions list (Casting marketplace)\n * @module hookmovies/pages/auditions\n *\n * Lists casting role postings via `hokListAuditions` with a status filter.\n * Talent open a posting to apply; casting teams open it to screen applicants.\n */\n\nimport { type FC, useState } from 'react';\nimport { Megaphone, Plus, MapPin, Languages, Clock } from 'lucide-react';\nimport { GlassCard } 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 { useAuditions, type HokAuditionStatus } from '../../hooks/useHookMoviesApi';\nimport { formatEnumLabel, formatMinorUnits, formatDate } from '../../utils/formatters';\n\nconst STATUS_OPTIONS: HokAuditionStatus[] = [\n 'OPEN',\n 'REVIEWING',\n 'CALLBACKS',\n 'CLOSED',\n 'CANCELLED',\n];\n\nconst PAGE_LIMIT = 20;\n\nexport const AuditionsPage: FC = () => {\n const { navigateTo } = useHookMovies();\n const [statusFilter, setStatusFilter] = useState<HokAuditionStatus | ''>('OPEN');\n const [page, setPage] = useState(0);\n\n const { data, isLoading, isError, refetch } = useAuditions(\n { status: statusFilter || undefined },\n { limit: PAGE_LIMIT, offset: page * PAGE_LIMIT }\n );\n\n const items = data?.items ?? [];\n\n return (\n <PageLayout\n title=\"Auditions\"\n description=\"Casting & talent marketplace\"\n purpose=\"Open casting calls across the network. Talent discover and apply to roles with a self-tape; casting teams screen, score, and shortlist applicants.\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('auditions/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 Post Role\n </button>\n }\n >\n <div className=\"mb-4 flex flex-wrap items-center gap-3\">\n <select\n value={statusFilter}\n onChange={(e) => {\n setStatusFilter(e.target.value as HokAuditionStatus | '');\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 {isLoading ? (\n <LoadingState label=\"Loading auditions…\" />\n ) : isError ? (\n <ErrorState onRetry={() => void refetch()} />\n ) : items.length === 0 ? (\n <EmptyState\n icon={<Megaphone className=\"h-12 w-12\" />}\n title=\"No auditions\"\n description=\"No casting calls match this filter.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('auditions/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 Post a Role\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((aud) => (\n <button\n key={aud.id}\n type=\"button\"\n onClick={() => navigateTo(`auditions/${aud.id}`)}\n className=\"text-left\"\n >\n <GlassCard treatment=\"metric\" className=\"flex h-full flex-col border-border-seam p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <h3 className=\"line-clamp-2 text-sm font-semibold text-text-primary\">\n {aud.roleName}\n </h3>\n <StatusBadge status={aud.status} />\n </div>\n {aud.production && (\n <p className=\"mt-1 text-xs text-text-secondary\">{aud.production.title}</p>\n )}\n {aud.isMinorRole && (\n <span className=\"mt-2 inline-block w-fit rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-[10px] text-status-warning-text\">\n Minor role — guardian consent required\n </span>\n )}\n {aud.description && (\n <p className=\"mt-2 line-clamp-2 text-xs text-text-secondary\">{aud.description}</p>\n )}\n <div className=\"mt-3 space-y-1 text-xs text-text-secondary\">\n <p className=\"font-medium text-text-primary\">\n {formatMinorUnits(aud.payMinorUnits, aud.currency)}\n </p>\n {aud.location && (\n <p className=\"flex items-center gap-1\">\n <MapPin className=\"h-3 w-3\" />\n {aud.location}\n </p>\n )}\n {aud.language && (\n <p className=\"flex items-center gap-1\">\n <Languages className=\"h-3 w-3\" />\n {aud.language}\n </p>\n )}\n {aud.submissionDeadline && (\n <p className=\"flex items-center gap-1\">\n <Clock className=\"h-3 w-3\" />\n Deadline{' '}\n {formatDate(aud.submissionDeadline, { hour: undefined, minute: undefined })}\n </p>\n )}\n </div>\n </GlassCard>\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 </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AuditionsPage.js","names":[],"sources":["../../../../src/hookmovies/pages/auditions/AuditionsPage.tsx"],"sourcesContent":["/**\n * Auditions list (Casting marketplace)\n * @module hookmovies/pages/auditions\n *\n * Lists casting role postings via `hokListAuditions` with a status filter.\n * Talent open a posting to apply; casting teams open it to screen applicants.\n */\n\nimport { type FC, useState } from 'react';\nimport {\n Megaphone,\n Plus,\n MapPin,\n Languages,\n Clock,\n Film,\n Banknote,\n ShieldAlert,\n ArrowUpRight,\n} from 'lucide-react';\nimport { GlassCard } 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 { useAuditions, type HokAuditionStatus } from '../../hooks/useHookMoviesApi';\nimport { formatEnumLabel, formatMinorUnits, formatDate } from '../../utils/formatters';\n\nconst STATUS_OPTIONS: HokAuditionStatus[] = [\n 'OPEN',\n 'REVIEWING',\n 'CALLBACKS',\n 'CLOSED',\n 'CANCELLED',\n];\n\n/** Filter chips: \"Any Status\" first, then each concrete status. `''` = no filter. */\nconst FILTER_CHIPS: ReadonlyArray<{ value: HokAuditionStatus | ''; label: string }> = [\n { value: '', label: 'Any Status' },\n ...STATUS_OPTIONS.map((s) => ({ value: s, label: formatEnumLabel(s) })),\n];\n\nconst PAGE_LIMIT = 20;\n\nexport const AuditionsPage: FC = () => {\n const { navigateTo } = useHookMovies();\n const [statusFilter, setStatusFilter] = useState<HokAuditionStatus | ''>('OPEN');\n const [page, setPage] = useState(0);\n\n const { data, isLoading, isError, refetch } = useAuditions(\n { status: statusFilter || undefined },\n { limit: PAGE_LIMIT, offset: page * PAGE_LIMIT }\n );\n\n const items = data?.items ?? [];\n\n const selectFilter = (value: HokAuditionStatus | '') => {\n setStatusFilter(value);\n setPage(0);\n };\n\n return (\n <PageLayout\n title=\"Auditions\"\n description=\"Casting & talent marketplace\"\n purpose=\"Open casting calls across the network. Talent discover and apply to roles with a self-tape; casting teams screen, score, and shortlist applicants.\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('auditions/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 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] transition-opacity\"\n >\n <Plus className=\"h-4 w-4\" aria-hidden=\"true\" />\n Post Role\n </button>\n }\n >\n {/* Status filter — horizontally scrollable pill group, scroll on small screens */}\n <div\n role=\"group\"\n aria-label=\"Filter auditions by status\"\n className=\"mb-5 -mx-1 flex items-center gap-2 overflow-x-auto px-1 pb-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\"\n >\n {FILTER_CHIPS.map((chip) => {\n const active = statusFilter === chip.value;\n return (\n <button\n key={chip.value || 'any'}\n type=\"button\"\n aria-pressed={active}\n onClick={() => selectFilter(chip.value)}\n className={`shrink-0 whitespace-nowrap rounded-full border px-3.5 py-1.5 text-xs font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] ${\n active\n ? 'border-action-primary-bg bg-action-primary-bg/10 text-action-primary-bg'\n : 'border-border-subtle text-text-secondary hover:border-border-strong hover:text-text-primary'\n }`}\n >\n {chip.label}\n </button>\n );\n })}\n </div>\n\n {isLoading ? (\n <LoadingState label=\"Loading auditions…\" />\n ) : isError ? (\n <ErrorState onRetry={() => void refetch()} />\n ) : items.length === 0 ? (\n <EmptyState\n icon={<Megaphone className=\"h-12 w-12\" />}\n title=\"No auditions\"\n description=\"No casting calls match this filter.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('auditions/new')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] transition-opacity\"\n >\n Post a Role\n </button>\n }\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3\">\n {items.map((aud) => (\n <button\n key={aud.id}\n type=\"button\"\n onClick={() => navigateTo(`auditions/${aud.id}`)}\n aria-label={`View casting call: ${aud.roleName}`}\n className=\"group text-left focus-visible:outline-none\"\n >\n <GlassCard\n treatment=\"metric\"\n className=\"flex h-full flex-col border-border-seam p-5 transition-all duration-200 group-hover:-translate-y-0.5 group-hover:border-action-primary-bg/40 group-focus-visible:border-action-primary-bg/60 group-focus-visible:ring-2 group-focus-visible:ring-[var(--color-focus-ring)]\"\n >\n {/* Header: role name + live status */}\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0\">\n <h3 className=\"line-clamp-2 text-sm font-semibold text-text-primary\">\n {aud.roleName}\n </h3>\n <p className=\"mt-1 flex items-center gap-1.5 text-xs text-text-secondary\">\n <Film className=\"h-3 w-3 shrink-0\" aria-hidden=\"true\" />\n <span className=\"truncate\">\n {aud.production?.title ?? 'Unassigned production'}\n </span>\n </p>\n </div>\n <StatusBadge status={aud.status} className=\"shrink-0\" />\n </div>\n\n {aud.isMinorRole && (\n <span className=\"mt-3 inline-flex w-fit items-center gap-1 rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-[10px] font-medium text-status-warning-text\">\n <ShieldAlert className=\"h-3 w-3\" aria-hidden=\"true\" />\n Minor role — guardian consent required\n </span>\n )}\n\n {aud.description && (\n <p className=\"mt-3 line-clamp-2 text-xs leading-relaxed text-text-secondary\">\n {aud.description}\n </p>\n )}\n\n {/* Pay — the headline number */}\n <div className=\"mt-4 flex items-center gap-2 rounded-lg border border-border-seam bg-bg-sunken px-3 py-2\">\n <Banknote\n className=\"h-4 w-4 shrink-0 text-status-success-text\"\n aria-hidden=\"true\"\n />\n <span className=\"text-sm font-semibold text-text-primary\">\n {formatMinorUnits(aud.payMinorUnits, aud.currency)}\n </span>\n </div>\n\n {/* Meta grid: location / language / deadline */}\n <dl className=\"mt-4 grid grid-cols-1 gap-y-2 text-xs text-text-secondary\">\n {aud.location && (\n <div className=\"flex items-center gap-1.5\">\n <MapPin className=\"h-3.5 w-3.5 shrink-0 text-text-muted\" aria-hidden=\"true\" />\n <dt className=\"sr-only\">Location</dt>\n <dd className=\"truncate\">{aud.location}</dd>\n </div>\n )}\n {aud.language && (\n <div className=\"flex items-center gap-1.5\">\n <Languages\n className=\"h-3.5 w-3.5 shrink-0 text-text-muted\"\n aria-hidden=\"true\"\n />\n <dt className=\"sr-only\">Language</dt>\n <dd className=\"truncate\">{aud.language}</dd>\n </div>\n )}\n {aud.submissionDeadline && (\n <div className=\"flex items-center gap-1.5\">\n <Clock className=\"h-3.5 w-3.5 shrink-0 text-text-muted\" aria-hidden=\"true\" />\n <dt className=\"sr-only\">Submission deadline</dt>\n <dd className=\"truncate\">\n Deadline{' '}\n {formatDate(aud.submissionDeadline, { hour: undefined, minute: undefined })}\n </dd>\n </div>\n )}\n </dl>\n\n {/* Footer CTA affordance */}\n <div className=\"mt-auto flex items-center justify-end pt-4\">\n <span className=\"inline-flex items-center gap-1 text-xs font-medium text-text-muted transition-colors group-hover:text-action-primary-bg\">\n View & apply\n <ArrowUpRight\n className=\"h-3.5 w-3.5 transition-transform group-hover:translate-x-0.5 group-hover:-translate-y-0.5\"\n aria-hidden=\"true\"\n />\n </span>\n </div>\n </GlassCard>\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 </PageLayout>\n );\n};\n"],"mappings":"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"}
|