Files
erika/app/(ui)/admin/login/page.tsx
T
2026-08-27 14:11:20 +00:00

161 lines
4.6 KiB
TypeScript

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/ui/tabs";
import { ExternalLink, KeyRound } from "lucide-react";
export const dynamic = "force-dynamic";
type LoginMethodProps = {
name: string;
description: string;
href: string;
configured: boolean;
setupVariables: string[];
resultVariables: string[];
};
function EnvironmentBlock({ variables }: { variables: string[] }) {
return (
<pre className="overflow-x-auto border bg-muted p-4 font-mono text-xs leading-6">
<code>{variables.map((variable) => `${variable}=\n`).join("")}</code>
</pre>
);
}
function LoginMethod({
name,
description,
href,
configured,
setupVariables,
resultVariables,
}: LoginMethodProps) {
return (
<Card>
<CardHeader>
<CardTitle>{name}</CardTitle>
<CardDescription>{description}</CardDescription>
<CardAction>
<Badge variant={configured ? "default" : "secondary"}>
{configured ? "Ready" : "Setup required"}
</Badge>
</CardAction>
</CardHeader>
<CardContent className="flex flex-col gap-5">
<div className="flex flex-col gap-2">
<h2 className="font-medium">Required before login</h2>
<p className="text-sm text-muted-foreground">
Add these values to the server environment and restart the app.
</p>
<EnvironmentBlock variables={setupVariables} />
</div>
<div className="flex flex-col gap-2">
<h2 className="font-medium">Returned after login</h2>
<p className="text-sm text-muted-foreground">
The callback page will show these values for your .env file.
</p>
<EnvironmentBlock variables={resultVariables} />
</div>
</CardContent>
<CardFooter className="border-t">
{configured ? (
<Button asChild>
<a href={href}>
<KeyRound data-icon="inline-start" />
Login with {name}
<ExternalLink data-icon="inline-end" />
</a>
</Button>
) : (
<Button disabled>
<KeyRound data-icon="inline-start" />
Login with {name}
</Button>
)}
</CardFooter>
</Card>
);
}
export default function AdminLoginPage() {
const youtubeConfigured = Boolean(
process.env.BASE_URL &&
process.env.YOUTUBE_CLIENT_ID &&
process.env.YOUTUBE_CLIENT_SECRET,
);
const tiktokConfigured = Boolean(
process.env.BASE_URL &&
process.env.TIKTOK_CLIENT_KEY &&
process.env.TIKTOK_CLIENT_SECRET,
);
return (
<>
<main className="mx-auto flex w-full max-w-4xl flex-col gap-6 p-4 pb-12 md:p-6">
<div>
<h1 className="text-3xl font-bold tracking-tight">Login</h1>
<p className="mt-1 text-muted-foreground">
Authorize a platform account and collect the generated .env values.
</p>
</div>
<Tabs defaultValue="youtube">
<TabsList className="grid w-full grid-cols-2 sm:w-fit sm:min-w-72">
<TabsTrigger value="youtube">YouTube</TabsTrigger>
<TabsTrigger value="tiktok">TikTok</TabsTrigger>
</TabsList>
<TabsContent value="youtube">
<LoginMethod
name="YouTube"
description="Authorize the channel used for video uploads."
href="/api/auth/youtube"
configured={youtubeConfigured}
setupVariables={[
"BASE_URL",
"YOUTUBE_CLIENT_ID",
"YOUTUBE_CLIENT_SECRET",
]}
resultVariables={[
"YOUTUBE_REFRESH_TOKEN",
"YOUTUBE_ACCESS_TOKEN",
]}
/>
</TabsContent>
<TabsContent value="tiktok">
<LoginMethod
name="TikTok"
description="Authorize the account used for profile data and video publishing."
href="/api/auth/tiktok"
configured={tiktokConfigured}
setupVariables={[
"BASE_URL",
"TIKTOK_CLIENT_KEY",
"TIKTOK_CLIENT_SECRET",
]}
resultVariables={[
"TIKTOK_ACCESS_TOKEN",
"TIKTOK_REFRESH_TOKEN",
"TIKTOK_OPEN_ID",
]}
/>
</TabsContent>
</Tabs>
</main>
</>
);
}