/* ============================================================================= * design_calc_sites.ts * 계산 자리 판(PLAN 504-2 · 요구 309-2) — B05 · B06 페이지 열 때 한 번 받아 페이지 수명 동안 씀. * 판 = 서버 `resources/master_template/calc_sites.json`(`common_util_calc_sites.py`) · 쓰기 = 시스템 관리자 * 「계산 자리」 창(`B01_Dashboard_UI_CalcSites.ts`). 열린 페이지는 다음 열기부터 · 못 받으면 전부 both. * ground_sample(G1) server = ground 단계가 격자 대신 서버 표본(`B05_Profile_Api_TerrainGrid.ts`) * corridor_mesh(D3) server = 3D 미리보기 워커 안 띄움 · 서버 모형만(`B05_Profile_UI_Corridor_Worker_Client.ts`) * quantity · carry · fixed_browser server = 조작 중 서버 창구(511-A · `design_calc_server.ts`) * haul(E2) 기본 server = /haul-plan · both = 브라우저가 배분 모듈을 그때 불러 셈(511-C · `B05_Profile_Api_HaulPlan.ts`) * ========================================================================== */ import { API_BASE_URL } from "@config/config_frontend"; export type CalcSiteValue = "both" | "server"; export interface CalcSiteGroup { key: string; nos: string[]; switchable: boolean; fixed: "both" | "server" | "browser" | null; why: string | null; /** 줄마다 까닭 열쇠(번호 → 열쇠) — 없으면 `why`. */ whys?: Record; } export interface CalcSitesBoard { version: number; sites: Record; groups: CalcSiteGroup[]; } async function request(init: RequestInit = {}): Promise { const path = init.method === "PUT" ? "/dashboard/admin/calc-sites" : "/dashboard/calc-sites"; const response = await fetch(`${API_BASE_URL}${path}`, { credentials: "include", headers: { "Content-Type": "application/json" }, ...init, }); const data = (await response.json()) as CalcSitesBoard & { detail?: string }; if (!response.ok) throw new Error(data.detail ?? `HTTP ${response.status}`); return data; } export const fetchCalcSites = (): Promise => request(); export const saveCalcSites = (sites: Record): Promise => request({ method: "PUT", body: JSON.stringify({ sites }) }); let opened: Promise> | null = null; let loaded: Record = {}; let project = ""; /** 페이지 열 때 — 새로 받음(앞 페이지 판 버림) · 서버 창구가 쓸 프로젝트. */ export function openCalcSites(projectId = project): Promise> { project = projectId; loaded = {}; opened = fetchCalcSites().then( (board) => (loaded = board.sites), () => ({}), ); return opened; } /** 이 묶음을 조작 중에도 서버가 셈? — 받기 전이면 받기를 기다림. */ export async function calcOnServer(key: string): Promise { return (await (opened ?? openCalcSites()))[key] === "server"; } /** 판에 both 일 때만 브라우저 셈 — 못 받음 · 받기 전 = 아님(기본 server 인 haul 줄). */ export async function calcInBrowser(key: string): Promise { return (await (opened ?? openCalcSites()))[key] === "both"; } /** 동기 자리용 — 받기 전 = both. */ export const calcOnServerNow = (key: string): boolean => loaded[key] === "server"; export const calcProjectId = (): string => project;