"use client"; import { useState } from "react"; import { useGame } from "@/hooks/useGame"; import VillageView from "@/components/game/VillageView"; import { engine, catRate } from "@/lib/game/engine"; import { APTITUDE_LABEL, PASSIVES } from "@/lib/game/data"; import type { Building, Cat, GameState } from "@/lib/game/types"; export default function Game() { const { state, dispatch } = useGame(); const [selectedCatId, setSelectedCatId] = useState(null); const [message, setMessage] = useState(null); if (!state) { return (
마을 불러오는 중…
); } const selectedCat = state.cats.find((c) => c.id === selectedCatId) ?? null; const run = (action: () => string | null | void) => { const error = dispatch(action); setMessage(error ?? null); }; return (
run(() => engine.adopt())} /> {message && (

⚠️ {message}

)}

🏗️ 생산 건물

고양이를 선택한 뒤 빈자리를 클릭해 배치하세요. 산출물은 직접 회수해야 합니다.

{state.buildings.map((b) => ( run(() => engine.assign(catId, b.id))} onUnassign={(catId) => run(() => engine.unassign(catId))} onCollect={() => run(() => engine.collect(b.id))} /> ))}

🐾 우리 고양이들 ({state.cats.length}/{state.hall.capacity})

{state.cats.map((cat) => ( setSelectedCatId(cat.id === selectedCatId ? null : cat.id) } /> ))}
); } function TopBar({ state, onAdopt }: { state: GameState; onAdopt: () => void }) { const full = state.cats.length >= state.hall.capacity; return (
🏛️ 마을 회관 Lv{state.hall.level} 🐱 {state.cats.length}/{state.hall.capacity}마리 🐟 {Math.floor(state.resources.fish)} 🪵 {Math.floor(state.resources.wood)}
); } function BuildingCard({ building, cats, selectedCat, onAssign, onUnassign, onCollect, }: { building: Building; cats: Cat[]; selectedCat: Cat | null; onAssign: (catId: string) => void; onUnassign: (catId: string) => void; onCollect: () => void; }) { const assignedCats = building.assigned .map((id) => cats.find((c) => c.id === id)) .filter((c): c is Cat => Boolean(c)); const totalRate = assignedCats.reduce( (sum, c) => sum + catRate(c, building.aptitude), 0, ); const stored = Math.floor(building.stored); const emptySlots = building.maxSlots - assignedCats.length; const canAssignSelected = selectedCat !== null && selectedCat.assignedTo !== building.id && selectedCat.aptitude[building.aptitude] > 0; return (

{building.emoji} {building.name} Lv{building.level}

필요 적성: {APTITUDE_LABEL[building.aptitude]}

생산 속도 {totalRate.toFixed(2)}/초

{assignedCats.map((cat) => ( ))} {Array.from({ length: emptySlots }).map((_, i) => ( ))}
); } function CatCard({ cat, buildings, selected, onSelect, }: { cat: Cat; buildings: Building[]; selected: boolean; onSelect: () => void; }) { const workplace = buildings.find((b) => b.id === cat.assignedTo); const expNeeded = cat.level * 60; return ( ); }