import { notFound } from "next/navigation"; import type { CSSProperties } from "react"; import QRCode from "qrcode"; import { db } from "@/lib/db"; import { SUPPORTS_QR, THEME_TOKENS } from "@/lib/constants"; import { buildPaymentUri } from "@/lib/payment-uri"; import { ProfileHeader } from "@/components/public/profile-header"; import { PaymentMethodCard } from "@/components/public/payment-method-card"; import { SocialLinksList } from "@/components/public/social-links-list"; export const revalidate = 60; type PublicProfilePageProps = { params: Promise<{ username: string; }>; }; export default async function PublicProfilePage({ params }: PublicProfilePageProps) { const { username } = await params; const normalizedUsername = username?.trim().toLowerCase(); if (!normalizedUsername) { notFound(); } const profile = await db.profile.findUnique({ where: { username: normalizedUsername }, include: { paymentMethods: { select: { id: true, type: true, label: true, value: true, network: true, description: true, isVisible: true }, where: { isVisible: true }, orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }] }, socialLinks: { select: { id: true, label: true, url: true }, where: { isVisible: true }, orderBy: [{ sortOrder: "asc" }, { createdAt: "asc" }] } } }); if (!profile || !profile.isPublic) { notFound(); } const methodsWithQr = await Promise.all( profile.paymentMethods.map(async (method) => { if (!SUPPORTS_QR.has(method.type)) { return { ...method, qrPayload: null, qrDataUrl: null }; } const qrPayload = buildPaymentUri(method.type, method.value, method.network); try { const qrDataUrl = await QRCode.toDataURL(qrPayload, { margin: 1, width: 280 }); return { ...method, qrPayload, qrDataUrl }; } catch { return { ...method, qrPayload, qrDataUrl: null }; } }) ); const tokens = THEME_TOKENS[profile.themeId] ?? THEME_TOKENS["terminal-dark"]; return (

Payment Methods

{profile.paymentMethods.length === 0 ? (

No payment methods published yet.

) : (
{methodsWithQr.map((method) => ( ))}
)}
); }