Files
invyone/frontend/components/admin/menu/MenuOverviewPanel.tsx
T

98 lines
3.8 KiB
TypeScript

"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>
);
}