1
0
Fork 0
polaris-task-force/src/app/(frontend)/voiceover/[id]/page.tsx
Z8MB1E 44b78ba7d9 feat(voiceover): add submission pages, recorder UI, and server actions
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>
2026-09-06 17:23:03 -04:00

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>
);
}