"use client";
import { useEffect, useRef } from "react";
import {
groupWindowTransitions,
rectificationBoardPeekCopy,
workingRectificationTime,
type RectificationBoardDiff,
} from "@/lib/rectification-board-model";
import {
workingRectificationHouseTable,
type RectificationCandidateResult,
} from "@/lib/rectification-candidate-result";
import {
windowScanLayerLabel,
type WindowScanLayer,
} from "@/lib/rectification-agentic/v9/refinement-packet";
import { RectificationHouseTableView } from "./rectification-house-table";
import { ConfirmationGateDisclosure, TechniqueAuditDisclosure } from "./technique-audit-disclosure";
function LayerChips({ layers }: Readonly<{ layers: readonly WindowScanLayer[] }>) {
if (layers.length === 0) return null;
return (
{layers.map((layer) => (
-
{windowScanLayerLabel(layer)}
))}
);
}
function RectificationBoardBody({
result,
savedStatus,
diff,
compact,
titleId,
onClose,
}: Readonly<{
result: RectificationCandidateResult | null;
savedStatus: "accepted" | "confirmed" | null;
diff: RectificationBoardDiff;
compact: boolean;
titleId: string;
onClose: () => void;
}>) {
const table = result ? workingRectificationHouseTable(result) : null;
const workingTime = workingRectificationTime(result);
const grouped = result ? groupWindowTransitions(result.windowTransitions) : [];
const scoringMinutes = grouped.filter((row) => row.scoringLayers.length > 0);
const displayMinutes = grouped.filter((row) => row.displayLayers.length > 0);
const changedHouses = new Set(diff.houseNumbers);
const changedMinutes = new Set(diff.transitionMinutes);
const stage = result?.precisionStage?.user_meaning
?? result?.natalRecast?.user_meaning
?? null;
const ledger = result?.eventDashaLedger ?? [];
const contrast = result?.lagnaContrast ?? null;
const agreement = result?.dashaAgreement ?? null;
const nakshatra = result?.nakshatraBoundary ?? null;
return (
<>
{diff.liveMessage}
{!table && (
补充经历后,这里会显示当前本命宫位和换升时刻。
)}
{table && (
{result && }
{savedStatus === "accepted" && result && result.techniqueAudit.length > 0 && (
)}
)}
{(scoringMinutes.length > 0 || displayMinutes.length > 0) && (
换升时刻
{scoringMinutes.length > 0 && (
{scoringMinutes.map((row) => {
const changed = changedMinutes.has(row.at);
const working = row.at === workingTime;
return (
-
{working ? 当前时间 : null}
{changed ? 已更新 : null}
);
})}
)}
{displayMinutes.length > 0 && (
显示层
{displayMinutes.length} 个时刻
{displayMinutes.map((row) => (
-
{changedMinutes.has(row.at) ? 已更新 : null}
))}
)}
)}
{contrast && (
两段本命上升
{contrast.user_meaning}
{contrast.intervals.map((interval) => (
-
{interval.start}-{interval.end}:{interval.lagna}
{interval.lords.l1 ? `;一/四/七/十宫主 ${[interval.lords.l1, interval.lords.l4, interval.lords.l7, interval.lords.l10].filter(Boolean).join("、")}` : ""}
))}
)}
{ledger.length > 0 && (
经历与大运对照
{ledger.length} 项
{ledger.map((item) => (
- {item.user_meaning}
))}
{agreement ? {agreement.user_meaning}
: null}
)}
{nakshatra?.near_boundary && nakshatra.user_meaning && (
交界节奏
{nakshatra.user_meaning}
)}
>
);
}
export function RectificationBoard({
result,
savedStatus,
diff,
compact,
open,
boardId,
titleId,
onClose,
}: Readonly<{
result: RectificationCandidateResult | null;
savedStatus: "accepted" | "confirmed" | null;
diff: RectificationBoardDiff;
compact: boolean;
open: boolean;
boardId: string;
titleId: string;
onClose: () => void;
}>) {
const dialogRef = useRef(null);
const body = (
);
useEffect(() => {
const node = dialogRef.current;
if (!compact || !node) return;
if (open) {
if (!node.open) node.showModal();
} else if (node.open) {
node.close();
}
}, [compact, open]);
useEffect(() => {
if (!compact) return;
const node = dialogRef.current;
if (!node) return;
const handleClose = () => onClose();
node.addEventListener("close", handleClose);
return () => node.removeEventListener("close", handleClose);
}, [compact, onClose]);
if (compact) {
return (
);
}
return (
);
}
export function RectificationBoardPeek({
result,
expanded,
boardId,
onOpen,
}: Readonly<{
result: RectificationCandidateResult | null;
expanded: boolean;
boardId: string;
onOpen: () => void;
}>) {
const peek = rectificationBoardPeekCopy(result);
return (
);
}