"use client"; import { useState } from "react"; import { readStreamableValue } from "ai/rsc"; import { Compass } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import Result from "@/components/result"; import ResultAI from "@/components/result-ai"; import BaziChartDisplay from "@/components/modes/bazi-chart"; import DateTimePicker, { nowDateString, nowTimeString, } from "@/components/shared/datetime-picker"; import HexagramInput from "@/components/shared/hexagram-input"; import RegionSelect, { useRegionLocation, } from "@/components/shared/region-select"; import { calculateBazi, type BaziChart } from "@/lib/calc/bazi"; import type { GuaResult } from "@/lib/calc/hexagram"; import { getCombinedAnswer } from "@/app/actions/combined"; import { ERROR_PREFIX } from "@/lib/constant"; export default function CombinedForm() { const [birthDate, setBirthDate] = useState("1990-01-01"); const [birthTime, setBirthTime] = useState("12:00"); const [unknownHour, setUnknownHour] = useState(false); const [gender, setGender] = useState<"male" | "female">("male"); const [birthProvince, setBirthProvince] = useState(""); const [birthCity, setBirthCity] = useState(""); const [currentProvince, setCurrentProvince] = useState(""); const [currentCity, setCurrentCity] = useState(""); const [calcDate, setCalcDate] = useState(nowDateString); const [calcTime, setCalcTime] = useState(nowTimeString); const [question, setQuestion] = useState(""); const [withHexagram, setWithHexagram] = useState(false); const [castMode, setCastMode] = useState<"online" | "offline">("online"); const [guaData, setGuaData] = useState(null); const [chart, setChart] = useState(null); const [completion, setCompletion] = useState(""); const [error, setError] = useState(""); const [isLoading, setIsLoading] = useState(false); const [showAi, setShowAi] = useState(false); const birthLocation = useRegionLocation(birthProvince, birthCity); const currentLocation = useRegionLocation(currentProvince, currentCity); const hexagramReady = !withHexagram || (question.trim() !== "" && currentLocation !== null && guaData !== null); function validate(): string | null { if (!birthLocation) { return "请选择出生地域"; } if (!currentLocation) { return "请选择当前所在地域"; } if (!question.trim()) { return "请输入问事内容"; } if (withHexagram && !guaData) { return "请完成六爻起卦,或取消附加六爻"; } return null; } function handlePreview() { const err = validate(); if (err) { setError(err); return; } setError(""); setChart( calculateBazi({ date: birthDate, time: unknownHour ? "12:00" : birthTime, gender, longitude: birthLocation!.longitude, unknownHour, }), ); setShowAi(false); setCompletion(""); } async function handleAnalyze() { const err = validate(); if (err) { setError(err); return; } if (!chart) { setChart( calculateBazi({ date: birthDate, time: unknownHour ? "12:00" : birthTime, gender, longitude: birthLocation!.longitude, unknownHour, }), ); } setError(""); setCompletion(""); setIsLoading(true); setShowAi(true); try { const { data, error: apiError } = await getCombinedAnswer({ birth: { date: birthDate, time: unknownHour ? "12:00" : birthTime, gender, longitude: birthLocation!.longitude, unknownHour, }, birthPlaceName: birthLocation!.name, currentPlaceName: currentLocation!.name, currentLongitude: currentLocation!.longitude, calcDate, calcTime, question, hexagram: withHexagram && guaData ? { guaMark: guaData.result.guaMark, guaTitle: guaData.result.guaTitle, guaResult: guaData.result.guaResult, guaChange: guaData.result.guaChange, } : undefined, }); if (apiError) { setError(apiError); return; } if (data) { let ret = ""; for await (const delta of readStreamableValue(data)) { if (typeof delta === "string" && delta.startsWith(ERROR_PREFIX)) { setError(delta.slice(ERROR_PREFIX.length)); return; } ret += delta ?? ""; setCompletion(ret); } } } catch (e) { setError(e instanceof Error ? e.message : String(e)); } finally { setIsLoading(false); } } return (

人和 · 生辰八字

{(["male", "female"] as const).map((g) => ( ))}

地利 · 当前位置

天时 · 测算时刻

问事