"use client"; import { motion } from "framer-motion"; import { Bot, Globe, LogIn, LogOut, ShoppingBag, Trophy, User, Users, Wifi, } from "lucide-react"; import { useEffect, useState } from "react"; import { useGameStore } from "@/lib/game-store"; import { useSessionStore } from "@/lib/session-store"; import { useUIStore, type Screen } from "@/lib/ui-store"; import { useI18n } from "@/lib/i18n"; import { getService } from "@/lib/online/service"; import { sound } from "@/lib/sound"; import { SUIT_SYMBOL } from "@/lib/hokm/types"; import { TopBar } from "./online/TopBar"; export function HomeScreen() { const { t, toggle } = useI18n(); const newMatch = useGameStore((s) => s.newMatch); const goGame = useUIStore((s) => s.goGame); const go = useUIStore((s) => s.go); const profile = useSessionStore((s) => s.profile); const isAuthed = useSessionStore((s) => s.isAuthed); const signOut = useSessionStore((s) => s.signOut); const nav = (screen: Screen) => { sound.init(); sound.play("click"); go(screen); }; const playVsComputer = () => { const you = profile?.displayName || t("seat.you"); newMatch({ names: [you, "آرش", "کیان", "نیلوفر"], targetScore: 7 }); goGame("home"); }; const playOnline = () => nav(isAuthed ? "online" : "auth"); return ( {/* logo */} ♠ {t("app.title")} {t("app.subtitle")} {/* primary actions */} } title={t("menu.online")} desc={t("menu.onlineDesc")} onClick={playOnline} primary /> } title={t("menu.vsComputer")} desc={t("menu.vsComputerDesc")} onClick={playVsComputer} /> {/* tiles */} } label={t("menu.profile")} onClick={() => nav("profile")} /> } label={t("menu.friends")} onClick={() => nav(isAuthed ? "friends" : "auth")} /> } label={t("menu.leaderboard")} onClick={() => nav("leaderboard")} /> } label={t("menu.shop")} onClick={() => nav("shop")} /> {/* footer */} {isAuthed ? ( {t("menu.signOut")} ) : ( go("auth")} className="btn-gold rounded-full px-4 py-2 text-sm flex items-center gap-2" > {t("menu.signIn")} )} {t("home.lang")} ); } function PrimaryCard({ icon, title, desc, onClick, primary, }: { icon: React.ReactNode; title: string; desc: string; onClick: () => void; primary?: boolean; }) { return ( {icon} {title} {desc} ); } function Tile({ icon, label, onClick, }: { icon: React.ReactNode; label: string; onClick: () => void; }) { return ( {icon} {label} ); } function OnlinePlayers() { const { t, locale } = useI18n(); const [count, setCount] = useState(null); useEffect(() => { let alive = true; const tick = async () => { try { const n = await getService().getOnlineCount(); if (alive) setCount(n); } catch { /* ignore */ } }; tick(); const id = setInterval(tick, 8000); return () => { alive = false; clearInterval(id); }; }, []); if (count == null) return null; const n = new Intl.NumberFormat(locale === "fa" ? "fa-IR" : "en-US").format(count); return ( {t("home.onlineCount", { n })} ); } function FloatingSuits() { const suits = Object.values(SUIT_SYMBOL); const items = Array.from({ length: 8 }, (_, i) => ({ s: suits[i % 4], left: `${(i * 13 + 6) % 95}%`, delay: i * 0.7, dur: 9 + (i % 4) * 2, size: 28 + (i % 3) * 18, })); return ( {items.map((it, i) => ( {it.s} ))} ); }
{t("app.subtitle")}