'use client'; import { useState } from 'react'; import { FoxButton } from '@fox/core/components/fox-button'; import { FoxButtonGroup } from '@fox/core/components/fox-button-group'; import { FoxIconButton } from '@fox/core/components/fox-icon-button'; import { FoxListContainer, type FoxListColumn, } from '@fox/core/components/fox-list-container'; import { useFeedback } from '@/app/_hooks/use-feedback'; import { useBlockingAction } from '@/app/_hooks/use-blocking-action'; import { flattenAdminMenuTree, formatActiveLabel, type AdminMenu, type AdminMenuNode, } from '@/lib/domain/admin-menu'; import { deleteAdminMenuAction } from '../_actions'; import { AdminMenuModal, type AdminMenuRole } from './admin-menu-modal'; import styles from './admin-menu-list.module.scss'; interface AdminMenuListProps { roots: AdminMenuNode[]; totalCount: number; roles: AdminMenuRole[]; } type ModalState = | { mode: 'create'; parent: AdminMenu; nextSortOrder: number } | { mode: 'edit'; menu: AdminMenuNode; parent: AdminMenu | null }; function findParent( roots: AdminMenuNode[], parentId: string | null ): AdminMenu | null { if (!parentId) return null; const stack = [...roots]; while (stack.length > 0) { const node = stack.pop(); if (!node) continue; if (node.id === parentId) return node; stack.push(...node.children); } return null; } export function AdminMenuList({ roots, totalCount, roles }: AdminMenuListProps) { const { showAlert, hideAlert, showToast } = useFeedback(); const [collapsedIds, setCollapsedIds] = useState>( new Set() ); const [modal, setModal] = useState(null); const [isDeleting, startDeleting] = useBlockingAction(); const rows = flattenAdminMenuTree(roots, collapsedIds); function toggle(id: string) { setCollapsedIds((current) => { const next = new Set(current); if (next.has(id)) { next.delete(id); } else { next.add(id); } return next; }); } function confirmDelete(menu: AdminMenuNode) { showAlert({ variant: 'danger', title: '메뉴를 삭제하시겠습니까?', message: `${menu.name} 메뉴를 삭제합니다. 삭제 후에는 되돌릴 수 없습니다.`, actions: ( { hideAlert(); startDeleting(async () => { const result = await deleteAdminMenuAction(menu.id); showToast( result.status === 'error' ? { variant: 'danger', message: result.message ?? '삭제하지 못했습니다.', } : { variant: 'success', message: '메뉴를 삭제했습니다.' } ); }); }} /> ), }); } const columns: FoxListColumn[] = [ { key: 'id', header: '메뉴번호', width: 120 }, { key: 'isActive', header: '활성여부', width: 120, render: (row) => ( {row.isActive ?