'use client'; import { useActionState, useEffect, useRef, useState } from 'react'; import { FoxButton } from '@fox/core/components/fox-button'; import { FoxInput } from '@fox/core/components/fox-input'; import { FoxModal } from '@fox/core/components/fox-modal'; import { FoxSelect } from '@fox/core/components/fox-select'; import { submitFormAction } from '@/app/_hooks/submit-form-action'; import { useFeedback } from '@/app/_hooks/use-feedback'; import { ACTIVE_OPTIONS, NEW_WINDOW_OPTIONS, type AdminMenu, type AdminMenuNode, } from '@/lib/domain/admin-menu'; import { ADMIN_MENU_DESCRIPTION_MESSAGES, ADMIN_MENU_NAME_MESSAGES, ADMIN_MENU_URL_MESSAGES, DESCRIPTION_VALIDATORS, INITIAL_ADMIN_MENU_FORM_STATE, NAME_VALIDATORS, URL_VALIDATORS, } from '@/lib/domain/admin-menu-form'; import { createAdminMenuAction, updateAdminMenuAction } from '../_actions'; import styles from './admin-menu-modal.module.scss'; export type AdminMenuRole = { id: string; name: string }; interface AdminMenuModalProps { /** 등록이면 상위가 될 메뉴, 수정이면 대상의 상위. 최상위 메뉴 수정 시에는 없다. */ parent: AdminMenu | null; /** 없으면 등록 팝업이다. */ menu?: AdminMenuNode; roles: AdminMenuRole[]; nextSortOrder: number; onClose: () => void; } export function AdminMenuModal({ parent, menu, roles, nextSortOrder, onClose, }: AdminMenuModalProps) { const isEdit = menu !== undefined; const { showToast } = useFeedback(); const formRef = useRef(null); const [state, formAction, isPending] = useActionState( isEdit ? updateAdminMenuAction : createAdminMenuAction, INITIAL_ADMIN_MENU_FORM_STATE ); const [roleId, setRoleId] = useState(menu?.roleId ?? roles[0]?.id ?? ''); const [isTopActive, setIsTopActive] = useState(menu?.isTopActive ?? false); const [opensNewWindow, setOpensNewWindow] = useState(true); const [isActive, setIsActive] = useState(menu?.isActive ?? true); useEffect(() => { if (state.status === 'success') { showToast({ variant: 'success', message: isEdit ? '메뉴를 수정했습니다.' : '메뉴를 등록했습니다.', }); onClose(); } }, [state, showToast, onClose, isEdit]); const errors = state.status === 'error' ? (state.errors ?? {}) : {}; return ( formRef.current?.requestSubmit()} /> } >
submitFormAction(event, formAction)} className={styles.fields} > {isEdit ? ( ) : ( )} {parent && ( )}
({ value: role.id, label: role.name }))} placeholder="메뉴권한을 선택하세요." value={roleId} onValueChange={setRoleId} error={Boolean(errors.roleId)} hint={errors.roleId} />
({ ...option }))} value={String(isTopActive)} onValueChange={(value) => setIsTopActive(value === 'true')} />
{/* 이슈: 백엔드에 대응 컬럼이 없어 저장되지 않는다(기획대로 화면에만 둔다). */}
({ ...option }))} value={String(opensNewWindow)} onValueChange={(value) => setOpensNewWindow(value === 'true')} />
({ ...option }))} value={String(isActive)} onValueChange={(value) => setIsActive(value === 'true')} />
{state.status === 'error' && state.message && (

{state.message}

)}
); }