"use client"; import { motion } from "framer-motion"; import { Bot, ChevronLeft, ChevronRight, Globe, LogIn, LogOut, Play, ShoppingBag, Trophy, User, Users, } from "lucide-react"; import { useEffect, useState } from "react"; import { Zap } from "lucide-react"; import { useGameStore, hasActiveMatch } from "@/lib/game-store"; import { pushNotification } from "@/lib/notification-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 { SPEED_TARGET_SCORE } from "@/lib/online/gamification"; import { SUIT_SYMBOL } from "@/lib/hokm/types"; import { cn } from "@/lib/cn"; import { TopBar } from "./online/TopBar"; export function HomeScreen() { const { t, toggle, locale } = 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 [speed, setSpeed] = useState(false); const playVsComputer = () => { // One game at a time: resume the running match instead of starting a new one. if (hasActiveMatch()) { useGameStore.getState().resume(); goGame("home"); pushNotification({ kind: "system", titleFa: "بازی در جریان", titleEn: "Game in progress", bodyFa: "ابتدا بازی فعلی را تمام کنید یا تسلیم شوید.", bodyEn: "Finish or forfeit your current game first.", icon: "🎮", }); return; } const you = profile?.displayName || t("seat.you"); newMatch({ names: [you, "آرش", "کیان", "نیلوفر"], targetScore: speed ? SPEED_TARGET_SCORE : 7, speed, }); goGame("home"); }; const playOnline = () => nav(isAuthed ? "online" : "auth"); const Chevron = locale === "fa" ? ChevronLeft : ChevronRight; return ( {/* logo */} ♠ {t("app.title")} {t("app.subtitle")} {/* HERO: play online */} {/* glow */} {t("menu.online")} {t("menu.onlineDesc")} {/* vs computer */} } title={t("menu.vsComputer")} desc={speed ? t("speed.desc") : t("menu.vsComputerDesc")} onClick={playVsComputer} /> {/* Normal / Speed mode picker */} setSpeed(false)} className={cn( "flex-1 rounded-xl py-2 text-xs font-bold transition flex items-center justify-center gap-1.5", !speed ? "btn-gold" : "text-cream/60 hover:text-cream" )} > {t("speed.normal")} setSpeed(true)} className={cn( "flex-1 rounded-xl py-2 text-xs font-bold transition flex items-center justify-center gap-1.5", speed ? "btn-gold" : "text-cream/60 hover:text-cream" )} > {t("speed.label")} {/* tiles */} } label={t("menu.profile")} tint="teal" onClick={() => nav("profile")} /> } label={t("menu.friends")} tint="sky" onClick={() => nav(isAuthed ? "friends" : "auth")} /> } label={t("menu.leaderboard")} tint="gold" onClick={() => nav("leaderboard")} /> } label={t("menu.shop")} tint="rose" 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} ); } const TILE_TINTS: Record = { teal: "bg-teal-500/15 text-teal-400", sky: "bg-sky-500/15 text-sky-400", gold: "bg-gold-500/15 text-gold-400", rose: "bg-rose-500/15 text-rose-400", }; function Tile({ icon, label, tint = "gold", onClick, }: { icon: React.ReactNode; label: string; tint?: keyof typeof TILE_TINTS; 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")}