import Link from "next/link"; import { getTranslations } from "next-intl/server"; import { isValidVerificationToken } from "@/actions/email-verify"; import { ContentCard, EmptyState } from "@/components/public/ui"; import { prisma } from "@/lib/prisma"; // Reads + writes the live users table — must never be statically rendered. export const dynamic = "force-dynamic"; type Status = "verified" | "already" | "invalid" | "unavailable"; export default async function VerifyPage({ searchParams, }: { searchParams: Promise<{ token?: string; email?: string }>; }) { const t = await getTranslations("pages.verify"); // Next 16: searchParams is a Promise. const { token = "", email = "" } = await searchParams; const normalisedEmail = email.trim().toLowerCase(); let status: Status = "invalid"; if (normalisedEmail && token) { const ok = await isValidVerificationToken(normalisedEmail, token); if (ok) { try { // mail is VARCHAR(500) and not unique in the emulator schema, so match // on the email and flip any matching unverified account(s). const user = await prisma.user.findFirst({ where: { mail: normalisedEmail }, select: { id: true, mailVerified: true }, }); if (!user) { status = "invalid"; } else if (user.mailVerified === "1") { status = "already"; } else { await prisma.user.update({ where: { id: user.id }, // users.mail_verified is a String flag ('0' / '1'). data: { mailVerified: "1" }, }); status = "verified"; } } catch { // DB unreachable — don't claim success. status = "unavailable"; } } else { status = "invalid"; } } return (
{status === "verified" ? (

{t("verifiedBody")}

{t("goToLogin")}
) : status === "already" ? (

{t("alreadyBody")}

{t("goToLogin")}
) : status === "unavailable" ? (

{t("unavailableBody")}

) : ( {t("invalidBody")}
{t("backToLogin")}
)}
); }