중간세이브 - 메뉴수정 - INVYONE 스튜디오 작업
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
"use client";
|
||||
|
||||
import React, { useMemo } from "react";
|
||||
import type { MenuItem } from "@/lib/api/menu";
|
||||
|
||||
interface Props {
|
||||
menus: MenuItem[];
|
||||
selectedId: string;
|
||||
}
|
||||
|
||||
export function MenuOverviewPanel({ menus, selectedId }: Props) {
|
||||
const stats = useMemo(() => {
|
||||
// 선택된 노드가 없으면 전체 기준, 있으면 L1이면 그 하위 전체, L2면 그 하위 자손
|
||||
const selected = menus.find((m) => String(m.objid ?? m.OBJID) === selectedId);
|
||||
const selectedLev = selected ? Number(selected.lev ?? selected.LEV ?? 1) : 0;
|
||||
|
||||
const descendants = (rootId: string): MenuItem[] => {
|
||||
const collected: MenuItem[] = [];
|
||||
const visit = (id: string) => {
|
||||
for (const m of menus) {
|
||||
const mid = String(m.objid ?? m.OBJID);
|
||||
const pid = String(m.parent_obj_id ?? m.PARENT_OBJ_ID ?? "0");
|
||||
if (pid === id) {
|
||||
collected.push(m);
|
||||
visit(mid);
|
||||
}
|
||||
}
|
||||
};
|
||||
visit(rootId);
|
||||
return collected;
|
||||
};
|
||||
|
||||
const scope = selected ? [selected, ...descendants(selectedId)] : menus;
|
||||
|
||||
const total = scope.length;
|
||||
const active = scope.filter((m) => (m.status ?? m.STATUS ?? "").toString().toLowerCase() === "active").length;
|
||||
const inactive = total - active;
|
||||
const linked = scope.filter((m) => (m.menu_url ?? m.MENU_URL ?? "").trim().length > 0).length;
|
||||
|
||||
return { total, active, inactive, linked, selectedLev, selectedName: selected ? (selected.menu_name_kor ?? selected.MENU_NAME_KOR ?? "") : "" };
|
||||
}, [menus, selectedId]);
|
||||
|
||||
return (
|
||||
<div className="v5-mm-pane on v5-mm-pane-wrap">
|
||||
<div style={{ marginBottom: "1.2rem" }}>
|
||||
<div className="v5-mm-step" style={{ marginBottom: ".4rem" }}>
|
||||
<span className="num">03</span>Overview
|
||||
</div>
|
||||
<h2 style={{ margin: 0, fontSize: "1.35rem", fontWeight: 700, letterSpacing: "-.025em" }}>
|
||||
{stats.selectedName || "전체 메뉴"}
|
||||
<span style={{ fontSize: ".72rem", color: "var(--v5-text-muted)", fontWeight: 500, marginLeft: ".55rem" }}>
|
||||
· {stats.total}개 항목
|
||||
</span>
|
||||
</h2>
|
||||
<p style={{ margin: ".35rem 0 0", fontSize: ".7rem", color: "var(--v5-text-muted)" }}>
|
||||
트리에서 L1을 선택하면 해당 카테고리의 하위 전체 통계가 표시됩니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="v5-mm-stats">
|
||||
<div className="v5-mm-stat">
|
||||
<div className="v5-mm-stat-lbl">전체</div>
|
||||
<div className="v5-mm-stat-val">
|
||||
<span className="n">{stats.total}</span>
|
||||
<span className="u">items</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="v5-mm-stat">
|
||||
<div className="v5-mm-stat-lbl">활성</div>
|
||||
<div className="v5-mm-stat-val">
|
||||
<span className="n ok">{stats.active}</span>
|
||||
<span className="u">/ {stats.total}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="v5-mm-stat">
|
||||
<div className="v5-mm-stat-lbl">비활성</div>
|
||||
<div className="v5-mm-stat-val">
|
||||
<span className="n off">{stats.inactive}</span>
|
||||
<span className="u">disabled</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="v5-mm-stat">
|
||||
<div className="v5-mm-stat-lbl">URL 연결</div>
|
||||
<div className="v5-mm-stat-val">
|
||||
<span className="n">{stats.linked}</span>
|
||||
<span className="u">linked</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ padding: "2rem 1rem", textAlign: "center", color: "var(--v5-text-muted)", fontSize: ".72rem",
|
||||
border: "1px dashed var(--v5-border)", borderRadius: "10px", background: "var(--v5-surface-solid)" }}>
|
||||
L2 메뉴를 클릭하면 Settings 탭으로 자동 전환되어 편집할 수 있습니다.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user