"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { Check, Coins, Sparkles } from "lucide-react"; import { useI18n } from "@/components/I18nProvider"; import { PlayerAvatar } from "@/components/PixelArt"; import { api } from "@/lib/client-api"; import type { CosmeticShopState, ProfileCosmeticId, } from "@/shared/profile-cosmetics"; export function CosmeticsShop({ accountId, avatarPath, initialShop, }: { accountId: string; avatarPath?: string | null; initialShop: CosmeticShopState; }) { const { t, formatNumber } = useI18n(); const router = useRouter(); const [shop, setShop] = useState(initialShop); const [busy, setBusy] = useState(null); const [error, setError] = useState(""); const [message, setMessage] = useState(""); async function change(action: "purchase" | "equip", cosmeticId: ProfileCosmeticId | null) { const requestId = cosmeticId ?? "none"; setBusy(requestId); setError(""); setMessage(""); try { const result = await api<{ shop: CosmeticShopState }>("cosmetics", { action, cosmeticId, }); setShop(result.shop); setMessage( action === "purchase" ? "Cosmetic purchased and equipped." : cosmeticId ? "Cosmetic equipped." : "Profile effect removed.", ); router.refresh(); } catch (reason) { setError((reason as Error).message); } finally { setBusy(null); } } return (
{t("THE EXPLORER’S WARDROBE")}

{t("Leave a little sparkle.")}

{t("Earn GeoCoins in solo expeditions and dress up your profile portrait.")}

{error &&

{t(error)}

} {message &&

{t(message)}

}
{shop.catalog.map((cosmetic) => { const owned = shop.owned.includes(cosmetic.id); const equipped = shop.equipped === cosmetic.id; const itemBusy = busy === cosmetic.id; return (
{t(cosmetic.rarity)} {equipped && ( )}

{t(cosmetic.name)}

{t(cosmetic.description)}

{owned ? ( ) : ( )}
); })}

{t("Cosmetics use GeoCoins for now. Payment options may be added later.")}

); }