- 부품 모달에 갈래 묻기 askChoice(취소 + 단추 여럿 · 고른 값 · 취소 = null) · 부품 모음 견본 한 칸 - 새 M02_MasterTemplete_Library_SameAsk.ts — 409 같은것 → 「그것을 씀 / 그래도 새로」 → 몸 씀 · 새로 로 다시 부름 - from-line(단가산출로도 저장 · 단가산출로 저장) · 공유 승인 · B09 내 자료집에 물음 · 취소 = 저장 안 함 - 새로 만들기(나무 · 목록 [생성])는 빈 문서라 서버가 묻지 않음 — 화면 손대지 않음 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
70 lines
3.0 KiB
TypeScript
70 lines
3.0 KiB
TypeScript
/* =============================================================================
|
|
* M02_MasterTemplete_Library_SameAsk.ts
|
|
* 서고 같은 내용 물음(733-3 · 서버 꼴 = 733-2) — 사람 길(단가산출로 저장 · 공유 승인 · B09 내 자료집 …)이
|
|
* 같은 층 같은 내용이면 서버 409 `detail = {같은것: [{키, 이름, 층, 주인}], 까닭}` →
|
|
* 물음 「같은 것 있음 — 그것을 씀 / 그래도 새로」 → 같은 부름을 몸 덧칸 `{씀: 키}` · `{새로: true}` 로 다시 ·
|
|
* 취소 = null. 물음 꼴 = 부품 `askChoice`.
|
|
* ========================================================================== */
|
|
|
|
import { currentLanguageIndex } from "@ui/ui_template_locale";
|
|
import { askChoice } from "@ui/ui_template_modal";
|
|
import { StaleError } from "./M02_MasterTemplete_Api_Fetch";
|
|
|
|
const TEXT = {
|
|
Title: ["같은 내용 있음", "Same content exists"],
|
|
Message: [
|
|
"이 층에 내용이 같은 문서가 이미 있음 — {list}",
|
|
"A document with the same content already exists on this layer — {list}",
|
|
],
|
|
More: [" 외 {n}", " and {n} more"],
|
|
Use: ["그것을 씀", "Use it"],
|
|
New: ["그래도 새로", "Create anyway"],
|
|
} as const;
|
|
const tx = (key: keyof typeof TEXT): string =>
|
|
TEXT[key][currentLanguageIndex as 0 | 1] ?? TEXT[key][0];
|
|
|
|
export interface SameHit {
|
|
키: string;
|
|
이름: string;
|
|
층: string;
|
|
주인: string | null;
|
|
}
|
|
/** 다시 보낼 몸 덧칸 — 그것을 씀 = 그 키 · 그래도 새로 = 새 문서 */
|
|
export interface SameExtra {
|
|
씀?: string;
|
|
새로?: boolean;
|
|
}
|
|
|
|
/** 서버 409 몸에서 같은 내용 문서 목록 — 없으면 null(다른 409 = 판 · 같은 이름 …) */
|
|
export const sameHits = (detail: unknown): SameHit[] | null => {
|
|
const list = (detail as { 같은것?: unknown } | null)?.같은것;
|
|
return Array.isArray(list) && list.length ? (list as SameHit[]) : null;
|
|
};
|
|
|
|
/** 물음 — 그것을 씀(첫 문서 = 먼저 만든 것) · 그래도 새로 · 취소 = null */
|
|
export async function askSame(hits: SameHit[]): Promise<SameExtra | null> {
|
|
const shown = hits.slice(0, 3).map((h) => `「${h.키} ${h.이름}」`);
|
|
const more = hits.length > 3 ? tx("More").replace("{n}", String(hits.length - 3)) : "";
|
|
const got = await askChoice({
|
|
title: tx("Title"),
|
|
message: tx("Message").replace("{list}", shown.join(" · ") + more),
|
|
choices: [
|
|
{ label: tx("New"), value: "new" },
|
|
{ label: tx("Use"), value: "use" },
|
|
],
|
|
});
|
|
return got === "use" ? { 씀: hits[0].키 } : got === "new" ? { 새로: true } : null;
|
|
}
|
|
|
|
/** `job(덧칸)` — 409 같은것이면 물은 뒤 덧칸을 넣어 한 번 더 · 취소 = null · 그 밖 실패 = 그대로 던짐 */
|
|
export async function withSameAsk<T>(job: (extra: SameExtra) => Promise<T>): Promise<T | null> {
|
|
try {
|
|
return await job({});
|
|
} catch (error) {
|
|
const hits = error instanceof StaleError ? sameHits(error.detail) : null;
|
|
if (!hits) throw error;
|
|
const extra = await askSame(hits);
|
|
return extra ? job(extra) : null;
|
|
}
|
|
}
|