/* ============================================================================= * m_settings_nav.ts * 시스템 설정 바로가기(334 · 요구 225-2 · 716-2) — 대시보드 설계 기본값 줄(`settingLinks` · 칸마다 한 줄 · * `?open=`) / M01 · M02 ☰ 메뉴(`pageLinks` · 페이지 둘 · `mountSettingsDrawer`). * ========================================================================== */ import { ROUTES, type RoutePath } from "@config/config_frontend"; import { currentLanguageIndex, ui_locales } from "@ui/ui_template_locale"; import { createStepBar } from "@ui/ui_template_workflow_layout"; import { setDrawerSteps } from "./app_shell"; import { currentRoute, navigateTo, takeLeaveGuard } from "./router"; interface SettingUser { role?: string; is_master?: boolean; company_id?: number | null; } /** key = 페이지 열쇠(☰ · 「m01」 「m02」) 또는 칸 열쇠(대시보드 줄 · 계산 자리 「calcSites」 = 창 504-2) · * group = 대시보드 설계 기본값 묶음 제목 */ export interface SettingLink { key: string; title: string; desc: string; route: RoutePath; query?: Record; group?: string; } function L(key: keyof typeof ui_locales): string { return ui_locales[key][currentLanguageIndex]; } const ICONS: Record = { m01: "🗄️", m02: "🧱" }; /** 설계 기본값 줄(대시보드) — 칸마다 한 줄 · 역할로 숨김 · M01 줄 `?open=`(칸 고름) · M02 줄 `?open=&root=`(27-1d). * 칸을 더할 때는 아래 표에 한 줄(m01 / m02 호출)만 더함. */ export function settingLinks(user: SettingUser, companyId: number | string | null): SettingLink[] { // 시스템 관리자는 고른 회사를 해시에 실음(29-1) const company: Record = user.role === "SYSTEM_ADMIN" && companyId ? { company: String(companyId) } : {}; const m01 = (key: string, title: string, desc: string, open?: string): SettingLink => ({ key, title, desc, route: ROUTES.M01_MASTER_DATA, query: open ? { open } : undefined, group: "마스터 데이터", }); const m02 = (title: string, open: string, root: string, desc: string): SettingLink => ({ key: open, title, desc, route: ROUTES.M02_MASTER_TEMPLATE, query: { open, root, ...company }, group: "마스터 템플릿", }); // 구조물 조합 기본 층 = 개인(123-1 · 누구든) · 개인 층 없음(회사 없음) = 아래 역할 규칙 const comboRoot = (fallback: string): string => (user.company_id ? "personal" : fallback); if (user.role === "SYSTEM_ADMIN") { const desc = L("B01_Dashboard_PermMasterWrite"); const read = L("B01_Dashboard_PermSourceRead"); return [ m01("m01", L("M01_Title"), read), m01("로직", L("B01_Dashboard_CardLogic"), read, "로직"), m01("옵션", L("B01_Dashboard_CardStructOptionDef"), desc, "옵션"), m01("별칭", L("B01_Dashboard_CardAliasLedger"), desc, "별칭"), m02(L("B01_Dashboard_CardSangeun"), "단가산출", comboRoot("master"), desc), m02(L("B01_Dashboard_CardPrecombo"), "일위대가조합", comboRoot("master"), desc), m02(L("B01_Dashboard_CardStructCombo"), "구조물조합", comboRoot("master"), desc), m02(L("B01_Dashboard_CardDrawing"), "도면", "master", desc), { key: "calcSites", title: L("B01_CalcSites_Title"), desc: L("B01_CalcSites_Desc"), route: ROUTES.B01_ACCOUNT, group: "계산", }, ]; } // 회사 수정 = 회사 관리자 · 회사 마스터(M02 accessFor 와 같은 규칙) const companyAdmin = user.role === "ADMIN" || user.is_master; const root = companyAdmin ? "company" : "personal"; const desc = [ L("B01_Dashboard_PermMasterRead"), L(companyAdmin ? "B01_Dashboard_PermCompanyWrite" : "B01_Dashboard_PermCompanyRead"), L("B01_Dashboard_PermPersonalWrite"), ].join(" · "); return [m02(L("B01_Dashboard_CardStructCombo"), "구조물조합", comboRoot(root), desc)]; } /** ☰ 메뉴 — 페이지 둘만(M01 = 시스템 관리자 · M02 = 누구나) · 열쇠 「m01」 「m02」 */ export function pageLinks(user: SettingUser, companyId: number | string | null): SettingLink[] { const combo = settingLinks(user, companyId).find((link) => link.key === "구조물조합"); const links: SettingLink[] = []; if (user.role === "SYSTEM_ADMIN") links.push({ key: "m01", title: L("B01_Dashboard_MasterElements"), desc: "", route: ROUTES.M01_MASTER_DATA, }); if (combo) links.push({ ...combo, key: "m02", title: L("M02_Title"), desc: "", group: undefined }); return links; } /** ☰ 진행 단계 자리 — 🏠 대시보드 + 페이지 둘 · 지금 페이지 강조(`activeKey` = 「m01」 「m02」) · * 같은 길(M02 → M02)은 머리 가드가 안 물어 여기서 먼저 */ export function mountSettingsDrawer( user: SettingUser, activeKey: string, companyId: number | string | null, ): void { const links = pageLinks(user, companyId); const bar = createStepBar( links.map((link) => link.title), links.findIndex((link) => link.key === activeKey), { orientation: "vertical", icons: links.map((link) => ICONS[link.key] ?? ""), routes: links.map((link) => link.route), homeButton: true, onStepClick: (index) => void go(links[index]), }, ); setDrawerSteps(bar); } async function go(link: SettingLink): Promise { const guard = link.route === currentRoute() ? takeLeaveGuard() : null; if (guard && !(await guard())) return; navigateTo(link.route, link.query); }