Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W4uKaV4ZBhsJN4GHG7yRj4
56 lines
2.5 KiB
TypeScript
56 lines
2.5 KiB
TypeScript
/* =============================================================================
|
|
* spreadsheet_link_set.ts (주인 D)
|
|
* 알약 키를 칸에 잇기 · 풀기 — 밖(M02 칸 지정 모달)에서 부르는 길(손잡이 `setLink`).
|
|
* 알약 누름(`spreadsheet_links.ts` `link`)과 같은 규칙: 키 하나 = 칸 하나 · 칸 하나 = 키 하나 ·
|
|
* 다른 시트에 있던 같은 키 연결은 빠짐. 바꿈은 `시트통째`(되돌리기 짝) · DOM 을 모름(시험이 Node 로 부름).
|
|
* ========================================================================== */
|
|
|
|
import { parseA1, toA1 } from "./spreadsheet_address";
|
|
import type { CellLink, Command, LinkMaterial, Workbook } from "./spreadsheet_types";
|
|
|
|
/** 연결에 같이 적을 알약 정보 — 없으면 있던 연결 것을 그대로 */
|
|
export interface LinkInfo {
|
|
이름?: string;
|
|
단위?: string;
|
|
자재?: LinkMaterial;
|
|
}
|
|
|
|
/** `칸`(A1 · null = 풀기)을 `sheetId` 시트에 이을 명령 — 바뀔 것 없으면 null · 칸 주소가 틀리면 false */
|
|
export function linkCommand(
|
|
book: Workbook,
|
|
sheetId: string,
|
|
key: string,
|
|
cell: string | null,
|
|
info: LinkInfo = {},
|
|
): Command | null | false {
|
|
const at = cell === null ? null : parseA1(cell.trim().toUpperCase());
|
|
if (cell !== null && !at) return false;
|
|
const a1 = at ? toA1(at.r, at.c) : null;
|
|
const old = book.시트.flatMap((s) => s.연결 ?? []).find((l) => l.키 === key);
|
|
const home = book.시트.find((s) => s.id === sheetId);
|
|
if (a1 && !home) return false;
|
|
if (a1 && home?.연결?.some((l) => l.키 === key && l.칸 === a1)) return null; // 이미 그 칸
|
|
const one: CellLink | null = a1 ? { 키: key, 칸: a1 } : null;
|
|
if (one) {
|
|
const 이름 = info.이름 ?? old?.이름;
|
|
const 단위 = info.단위 ?? old?.단위;
|
|
const 자재 = info.자재 ?? old?.자재;
|
|
if (이름) one.이름 = 이름;
|
|
if (단위) one.단위 = 단위;
|
|
if (자재) one.자재 = 자재;
|
|
}
|
|
const commands: Command[] = [];
|
|
for (const s of book.시트) {
|
|
const was = s.연결 ?? [];
|
|
const rest = was.filter((l) => l.키 !== key && !(s === home && a1 && l.칸 === a1));
|
|
const next = s === home && one ? [...rest, one] : rest;
|
|
if (next.length === was.length && next.every((l, i) => l === was[i])) continue;
|
|
const copy = structuredClone(s);
|
|
if (next.length) copy.연결 = next;
|
|
else delete copy.연결;
|
|
commands.push({ 종류: "시트통째", 시트: copy });
|
|
}
|
|
if (!commands.length) return null;
|
|
return commands.length === 1 ? commands[0] : { 종류: "묶음", 명령: commands };
|
|
}
|