"use client"; import { useCallback, useEffect, useState } from "react"; import { Play } from "lucide-react"; import { bool } from "aimless.js"; import Coin from "@/components/coin"; import Hexagram from "@/components/hexagram"; import { Button } from "@/components/ui/button"; import { buildHexagramList, COIN_OPTIONS, computeGuaResult, type GuaResult, YAO_LABELS, } from "@/lib/calc/hexagram"; const AUTO_DELAY = 800; interface HexagramInputProps { mode: "online" | "offline"; enabled: boolean; active: boolean; onStart: () => void; onResult: (data: GuaResult) => void; onClear: () => void; } export default function HexagramInput({ mode, enabled, active, onStart, onResult, onClear, }: HexagramInputProps) { const [frontList, setFrontList] = useState([true, true, true]); const [rotation, setRotation] = useState(false); const [hexagramList, setHexagramList] = useState([]); const [offlineCounts, setOfflineCounts] = useState<(number | null)[]>( Array(6).fill(null), ); const complete = hexagramList.length === 6; useEffect(() => { setHexagramList([]); setOfflineCounts(Array(6).fill(null)); setRotation(false); }, [mode]); useEffect(() => { if (!active) { setHexagramList([]); setOfflineCounts(Array(6).fill(null)); setRotation(false); } }, [active]); const finishList = useCallback( (list: GuaResult["list"]) => { const result = computeGuaResult(list); if (result) { onResult({ list, result }); } }, [onResult], ); const onTransitionEnd = useCallback(() => { setRotation(false); const frontCount = frontList.reduce( (acc, val) => (val ? acc + 1 : acc), 0, ); setHexagramList((list) => { const newList = [ ...list, { change: frontCount === 0 || frontCount === 3, yang: frontCount >= 2, separate: list.length === 3, }, ]; if (newList.length === 6) { finishList(newList); } return newList; }); }, [frontList, finishList]); const startOnlineCast = useCallback(() => { if (rotation || !enabled || !active || hexagramList.length >= 6) { return; } setFrontList([bool(), bool(), bool()]); setRotation(true); }, [rotation, enabled, active, hexagramList.length]); useEffect(() => { if (mode !== "online" || !enabled || !active || rotation || complete) { return; } const timer = setTimeout(startOnlineCast, AUTO_DELAY); return () => clearTimeout(timer); }, [ mode, enabled, active, rotation, complete, hexagramList.length, startOnlineCast, ]); function handleOfflineSelect(index: number, frontCount: number) { const next = [...offlineCounts]; next[index] = frontCount; setOfflineCounts(next); } function confirmOffline() { if (offlineCounts.some((v) => v === null)) { return; } const list = buildHexagramList(offlineCounts as number[]); finishList(list); setHexagramList(list); } function handleReset() { setHexagramList([]); setOfflineCounts(Array(6).fill(null)); setRotation(false); onClear(); } const offlineReady = offlineCounts.every((v) => v !== null); if (!enabled) { return (

请先填写问事、地域和起卦时辰

); } if (!active) { return (

信息已填写完毕,确认无误后手动开始起卦

); } return (
{mode === "online" && ( <> 🎲 第{" "} {complete ? "6/6" : `${hexagramList.length + (rotation ? 1 : 0)}/6`} {" "} 次卜筮 {rotation && ( 铜钱旋转中… )} )} {mode === "offline" && !complete && (

人工抛铜钱后,按从下到上(初爻→上爻)录入每爻结果

{YAO_LABELS.map((label, index) => (
{label} {COIN_OPTIONS.map((opt) => ( ))}
))}
)} {hexagramList.length > 0 && (
{complete && ( <>

六爻已齐,请在下方点击「AI 解读」

)}
)}
); }