Add /voiceover script list and take detail pages, teleprompter reader, voice capture/recorder components, submission server actions with a 9 MB audio cap, and a Contribute > Voiceover entry in the user menu. Ultraworked with [Sisyphus](https://github.com/code-yeongju/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
import type { Metadata } from "next";
|
|
import config from "@payload-config";
|
|
import { getPayload } from "payload";
|
|
import { headers as nextHeaders } from "next/headers";
|
|
import Link from "next/link";
|
|
import { notFound, redirect } from "next/navigation";
|
|
import { ArrowLeftIcon, MicIcon } from "lucide-react";
|
|
|
|
import { VoiceoverRecorder } from "@/components/frontend/voiceover/VoiceoverRecorder";
|
|
import { getScriptForUser } from "@/lib/voiceover";
|
|
import { isPayloadUser } from "@/utils/access-control/isPayloadUser";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Record voiceover — Polaris Task Force",
|
|
description: "Read a Polaris Task Force voiceover script and submit a recording.",
|
|
};
|
|
|
|
export default async function VoiceoverScriptPage({
|
|
params,
|
|
}: {
|
|
readonly params: Promise<{ id: string }>;
|
|
}) {
|
|
const { id } = await params;
|
|
const scriptId = Number(id);
|
|
if (!Number.isInteger(scriptId) || scriptId < 1) notFound();
|
|
|
|
const headers = await nextHeaders();
|
|
const payloadConfig = await config;
|
|
const payload = await getPayload({ config: payloadConfig });
|
|
const { user } = await payload.auth({ headers, canSetHeaders: false });
|
|
|
|
if (!isPayloadUser(user)) {
|
|
redirect(`/login?returnTo=${encodeURIComponent(`/voiceover/${id}`)}`);
|
|
}
|
|
|
|
const script = await getScriptForUser(payload, user, scriptId);
|
|
if (!script) notFound();
|
|
|
|
return (
|
|
<div className="flex min-w-0 flex-col gap-6 p-5">
|
|
<Link
|
|
href="/voiceover"
|
|
className="flex w-fit items-center gap-1 text-sm text-muted-foreground transition-colors hover:text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
>
|
|
<ArrowLeftIcon className="size-3" />
|
|
Voiceover scripts
|
|
</Link>
|
|
|
|
<div className="flex items-start gap-3">
|
|
<MicIcon className="mt-0.5 size-5 shrink-0 text-muted-foreground" />
|
|
<div className="flex min-w-0 flex-col gap-1">
|
|
<h1 className="text-lg font-semibold">{script.title}</h1>
|
|
<p className="text-sm text-muted-foreground">
|
|
Read the script at your pace, then submit one clear take for review.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<VoiceoverRecorder script={script} />
|
|
</div>
|
|
);
|
|
}
|