Files
HokmPlay/src/components/screens/OnlineLobbyScreen.tsx
T

143 lines
5.5 KiB
TypeScript
Raw Normal View History

"use client";
import { motion } from "framer-motion";
import { Coins, Lock, Trophy, Users } from "lucide-react";
import { useState } from "react";
import { ScreenHeader, ScreenShell } from "@/components/online/ScreenHeader";
import { CoinsPill } from "@/components/online/CoinsPill";
import { MATCH_LEAGUES, leagueById } from "@/lib/online/gamification";
import { useOnlineStore } from "@/lib/online-store";
import { useSessionStore } from "@/lib/session-store";
import { useUIStore } from "@/lib/ui-store";
import { useI18n } from "@/lib/i18n";
import { cn } from "@/lib/cn";
export function OnlineLobbyScreen() {
const { t, locale } = useI18n();
const createRoom = useOnlineStore((s) => s.createRoom);
const startMatchmaking = useOnlineStore((s) => s.startMatchmaking);
const go = useUIStore((s) => s.go);
const profile = useSessionStore((s) => s.profile);
const coins = profile?.coins ?? 0;
const level = profile?.level ?? 1;
const [leagueId, setLeagueId] = useState(MATCH_LEAGUES[0].id);
const league = leagueById(leagueId);
const entry = league.entry;
const lockedLeague = level < league.minLevel;
// Private rooms with friends are free.
const onCreate = async () => {
await createRoom({ targetScore: 7, stake: 0, ranked: false });
go("room");
};
// Ranked random always costs the entry (you stake it).
const onRandom = async () => {
if (lockedLeague) return;
if (coins < entry) {
go("buycoins");
return;
}
await startMatchmaking({ ranked: true, stake: entry });
go("matchmaking");
};
return (
<ScreenShell>
<ScreenHeader title={t("lobby.title")} right={<CoinsPill />} />
{/* league pick (only for ranked) */}
<div className="glass rounded-2xl p-4 mb-4">
<div className="flex items-center gap-1.5 text-sm text-cream/70 mb-2.5">
<Trophy className="size-4 text-gold-400" />
{t("lobby.chooseLeague")}
</div>
<div className="space-y-2">
{MATCH_LEAGUES.map((l) => {
const locked = level < l.minLevel;
const active = l.id === leagueId;
return (
<button
key={l.id}
disabled={locked}
onClick={() => setLeagueId(l.id)}
className={cn(
"w-full rounded-2xl p-3 flex items-center gap-3 border text-start transition",
active
? "border-gold-500/70 bg-gold-500/10"
: "border-navy-700/60 bg-navy-900/50 hover:border-navy-600",
locked && "opacity-50 cursor-not-allowed"
)}
>
<span
className="size-10 rounded-xl flex items-center justify-center text-xl shrink-0"
style={{ background: l.color + "22" }}
>
{l.icon}
</span>
<span className="flex-1 min-w-0">
<span className="block text-sm font-black text-cream">
{locale === "fa" ? l.nameFa : l.nameEn}
</span>
<span className="block text-[11px] text-cream/55">
{locale === "fa" ? l.descFa : l.descEn}
</span>
</span>
{locked ? (
<span className="text-[11px] text-rose-300 flex items-center gap-1 shrink-0">
<Lock className="size-3.5" />
{t("lobby.lvl")} {l.minLevel}
</span>
) : (
<span className="flex items-center gap-1 text-gold-300 font-black text-sm shrink-0">
{l.entry.toLocaleString()}
<Coins className="size-3.5" />
</span>
)}
</button>
);
})}
</div>
{!lockedLeague && coins < entry && (
<p className="text-rose-300 text-xs mt-2 text-center">{t("lobby.needCoins")}</p>
)}
</div>
<div className="space-y-3">
<motion.button
whileTap={{ scale: 0.985 }}
onClick={onRandom}
className="press-3d btn-gold w-full rounded-3xl p-5 flex items-center gap-4 text-start"
>
<span className="grid size-12 place-items-center rounded-2xl bg-black/15 text-[#2a1f04]">
<Trophy className="size-6" />
</span>
<span className="flex-1">
<span className="block text-lg font-black text-[#2a1f04]">{t("lobby.random")}</span>
<span className="block text-xs text-[#2a1f04]/70">{t("lobby.randomDesc")}</span>
</span>
<span className="flex items-center gap-1 text-[#2a1f04] font-black">
{entry}
<Coins className="size-4" />
</span>
</motion.button>
<motion.button
whileTap={{ scale: 0.985 }}
onClick={onCreate}
className="press-3d glass w-full rounded-3xl p-5 flex items-center gap-4 text-start"
>
<span className="grid size-12 place-items-center rounded-2xl bg-teal-500/15 text-teal-300">
<Users className="size-6" />
</span>
<span className="flex-1">
<span className="block text-lg font-black text-cream">{t("lobby.createRoom")}</span>
<span className="block text-xs text-cream/55">{t("lobby.createDesc")}</span>
</span>
<span className="text-teal-300 font-bold text-sm">{t("lobby.free")}</span>
</motion.button>
</div>
</ScreenShell>
);
}