import { redirect } from "next/navigation"; import { getFormatter, getTranslations } from "next-intl/server"; import { claimReferral } from "@/actions/referral"; import Link from "@/components/link"; import { CurrencyIcon, type CurrencyKind, } from "@/components/shared/currency-icon"; import { ProfileImage } from "@/components/shared/profile-image"; import { UserAvatarThumbnail } from "@/components/shared/user-avatar-thumbnail"; import { SurfaceCard } from "@/components/surface-card"; import { auth } from "@/lib/auth"; import { avatarImageUrl } from "@/lib/format"; import { loadUserDashboard } from "@/lib/services/user-dashboard"; import CopyReferralButton from "./CopyReferralButton"; import styles from "./dashboard.module.css"; export async function generateMetadata() { const t = await getTranslations("pages.myDashboard"); return { title: t("title") }; } export default async function MePage({ searchParams, }: { searchParams: Promise<{ claimed?: string; error?: string }>; }) { const session = await auth(); if (!session?.user?.id) redirect("/login"); const userId = Number(session.user.id); if (!Number.isFinite(userId) || userId <= 0) redirect("/login"); const [t, format, { claimed, error }] = await Promise.all([ getTranslations("pages.myDashboard"), getFormatter(), searchParams, ]); let data: Awaited>; try { data = await loadUserDashboard(userId); } catch { return (

{t("loadError")}

{t("retry")}
); } const user = data.userRows[0]; if (!user) return (

{t("loadError")}

{t("login")}
); const { hotelName, neededRaw, rewardAmountRaw, currencySettings, alertRaw, recentRooms, badges, userSettingsRows, friendCountRows, unreadCountRows, referralsRows, friends, currencyRows, } = data; const userSettings = userSettingsRows[0]; const friendCount = Number(friendCountRows[0]?.value ?? 0); const unreadCount = Number(unreadCountRows[0]?.value ?? 0); const needed = Math.max(1, Number.parseInt(neededRaw ?? "5", 10) || 5); const rewardAmount = Number.parseInt(rewardAmountRaw ?? "30", 10) || 0; const rewardCurrency = ( currencySettings.referral_reward_currency_type ?? currencySettings.referral_reward_currency ?? "diamonds" ) .trim() .toLowerCase(); const rewardKind = ["credits", "duckets", "diamonds", "points"].includes( rewardCurrency, ) ? (rewardCurrency as CurrencyKind) : null; const referralTotal = Math.max( 0, Number(referralsRows[0]?.referralsTotal ?? 0), ); const canClaim = referralTotal >= needed; const remaining = Math.max(0, needed - referralTotal); const onlineFriends = [ ...new Map( friends .filter((friend) => friend.online === "1") .map((friend) => [friend.id, friend]), ).values(), ]; const date = (value: number) => value ? format.dateTime(new Date(value * 1000), { dateStyle: "medium" }) : t("never"); const referralLink = `/register?ref=${encodeURIComponent(user.username)}`; const avatarFull = avatarImageUrl(user.look, { direction: 2 }); const wallet = [ { kind: "credits", value: user.credits }, { kind: "duckets", value: currencyRows === null ? null : (currencyRows.find((row) => row.type === 0)?.amount ?? 0), }, { kind: "diamonds", value: currencyRows === null ? null : (currencyRows.find((row) => row.type === 5)?.amount ?? 0), }, ] as const; const errorKey = error && ["not_enough", "no_referrals", "bad_config", "ratelimit"].includes(error) ? error : "error"; return (
{claimed && (

{t("claimed")}

)} {error && (

{t(`errors.${errorKey}`)}

)}

{t("welcome", { hotel: hotelName })}

{user.username}

{user.motto || t("noMotto")}

{t("registered", { date: date(user.accountCreated) })} ·{" "} {t("lastOnline", { date: date(user.lastOnline) })}

{t("enter", { hotel: hotelName })} →
{alertRaw &&

{alertRaw}

}
{wallet.map((currency) => (
{currency.value === null ? "—" : format.number(currency.value)} {t(`currencies.${currency.kind}`)}
))}
{onlineFriends.length === 0 ? (

{t("noOnlineFriends")}

) : (
{onlineFriends.map((friend) => (
{friend.username} {friend.motto || t("noMotto")}
))}
)}

{t("roomsHint")}

{recentRooms.length === 0 ? (

{t("noRooms")}

) : (
{recentRooms.map((room) => ( {room.name} {room.ownerName} · {room.users}/{room.usersMax} ))}
)}
{[ { label: t("achievements"), value: format.number(userSettings?.achievementScore ?? 0), }, { label: t("respects"), value: format.number(userSettings?.respectsReceived ?? 0), }, { label: t("friends"), value: format.number(friendCount) }, { label: t("lastLogin"), value: date(user.lastLogin) }, ].map((stat) => (
{stat.label}
{stat.value}
))}
); }