import Link from "next/link"; import { redirect } from "next/navigation"; import { getServerSession } from "next-auth"; import { authOptions } from "@/lib/auth"; import { prisma } from "@/lib/db"; import { AccountPrivacyActions } from "@/components/AccountPrivacyActions"; import { CreditPurchasePanel } from "@/components/CreditPurchasePanel"; import { PlanBillingActions } from "@/components/PlanBillingActions"; import { DashboardShell } from "@/components/DashboardShell"; import { UpgradeProButton } from "@/components/UpgradeProButton"; import { getUserApiKeyStatus } from "@/lib/api-keys"; import { getApiRateLimitStatus } from "@/lib/api-rate-limit"; import { ApiKeySettings } from "@/components/ApiKeySettings"; import { hasProFeatures, isSelfHostedEdition } from "@/lib/edition"; import { EXTENSION_KIND, getQuotaExtensionUsage } from "@/lib/quota-extensions"; import { getQuotaInfo } from "@/lib/quota"; import { isBillingDevMock, isStripeConfigured } from "@/lib/stripe"; import { CreditPurchaseStatus } from "@prisma/client"; const PLAN_LABELS = { FREE: "Bedroom Producer", PREMIUM: "Pro", } as const; function InfoRow({ label, value }: { label: string; value: string }) { return (
{label}
{value}
); } export default async function SettingsPage() { const session = await getServerSession(authOptions); if (!session?.user?.email) redirect("/"); const user = await prisma.user.findUnique({ where: { email: session.user.email }, include: { youtubeConnection: true }, }); if (!user) redirect("/"); const quota = await getQuotaInfo(user.id); const selfHosted = isSelfHostedEdition(); const proFeatures = hasProFeatures(user.plan); const recentCreditPurchases = await prisma.creditPurchase.findMany({ where: { userId: user.id, status: CreditPurchaseStatus.COMPLETED }, orderBy: { completedAt: "desc" }, take: 5, }); const extensionUsage = !selfHosted && user.plan === "PREMIUM" ? await getQuotaExtensionUsage(user.id) : null; const apiRateExtensionUsage = proFeatures ? await getQuotaExtensionUsage(user.id, EXTENSION_KIND.API_RATE_LIMIT) : null; const apiKeyStatus = proFeatures ? await getUserApiKeyStatus(user.id) : null; const apiRateLimit = proFeatures ? await getApiRateLimitStatus(user.id) : null; const planLabel = selfHosted ? "Self-hosted" : PLAN_LABELS[user.plan]; const youtube = user.youtubeConnection; const channelUrl = youtube ? `https://www.youtube.com/channel/${youtube.channelId}` : null; return (

Settings

Account information

YouTube

{youtube ? (
) : (

YouTube account not connected.

)} {channelUrl && ( Go to your channel )}

To refresh your YouTube permissions,{" "} sign out and sign in again .

Plan & billing

Video quota remaining

{quota.totalAvailable} {" "} of {quota.limit + quota.extraCredits} videos

{quota.used} monthly used {quota.extraCredits > 0 ? ` · ${quota.extraCredits} extras` : ""} {quota.bonusQuota > 0 ? ` · +${quota.bonusQuota} bonus` : ""}

{`Includes monthly + purchased extras · monthly resets on ${quota.resetsIn}`}

{user.plan === "PREMIUM" && user.subscribedAt && ( )} {user.plan === "PREMIUM" && ( )} {extensionUsage && ( )}
{user.plan === "FREE" ? ( <>

for 50 videos/month, 1080p, API access, and lossless audio.

{!selfHosted && ( ({ id: p.id, credits: p.credits, amountCents: p.amountCents, completedAt: p.completedAt?.toISOString() ?? null, }))} /> )} ) : ( <> {extensionUsage && }

Pro uses your monthly allocation first, then any never-expiring extra credits.

)}
{proFeatures && apiKeyStatus && apiRateLimit && apiRateExtensionUsage && (

API access

)}

Account deletion & data

Request a copy of your data or permanently delete your account and associated uploads.

); }