Compare commits

...

2 Commits

2 changed files with 84 additions and 73 deletions

View File

@@ -67,21 +67,6 @@ export const getAdminMenuListByParentSeq = async (parentSeq: number, pageNum: nu
return { content: [], pageNum: 1, pageSize: 0, totalContent: 0, totalPage: 0, isFirstPage: true, isLastPage: true }; return { content: [], pageNum: 1, pageSize: 0, totalContent: 0, totalPage: 0, isFirstPage: true, isLastPage: true };
}; };
// parentSeq로 어드민 메뉴 목록 조회 (페이징 없이 전체 목록)
export const getAdminMenuListByParentSeqAll = async (parentSeq: number): Promise<AdminMenu[]> => {
const response = await axios.get<AdminMenuResponse>(`/admin/menu/listByParentSeq/${parentSeq}`);
const resultData = response.data.resultData;
// 페이징 형태의 응답인 경우 content 배열 반환
if (resultData && resultData.content && Array.isArray(resultData.content)) {
return resultData.content;
}
// 배열 형태의 응답인 경우 그대로 반환
if (Array.isArray(resultData)) {
return resultData;
}
return [];
};
// adminMenuSeq로 어드민 메뉴 조회 // adminMenuSeq로 어드민 메뉴 조회
export const getAdminMenu = async (adminMenuSeq: number): Promise<AdminMenu> => { export const getAdminMenu = async (adminMenuSeq: number): Promise<AdminMenu> => {
const response = await axios.get<AdminMenuResponse>(`/admin/menu/${adminMenuSeq}`); const response = await axios.get<AdminMenuResponse>(`/admin/menu/${adminMenuSeq}`);

View File

@@ -160,6 +160,7 @@ const AdminMenuManagement: React.FC = () => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [modalVisible, setModalVisible] = useState(false); const [modalVisible, setModalVisible] = useState(false);
const [deleteModalVisible, setDeleteModalVisible] = useState(false); const [deleteModalVisible, setDeleteModalVisible] = useState(false);
const [hasChildMenus, setHasChildMenus] = useState(false);
const [iconPickerVisible, setIconPickerVisible] = useState(false); const [iconPickerVisible, setIconPickerVisible] = useState(false);
const [isEditMode, setIsEditMode] = useState(false); const [isEditMode, setIsEditMode] = useState(false);
const [selectedMenu, setSelectedMenu] = useState<AdminMenu | null>(null); const [selectedMenu, setSelectedMenu] = useState<AdminMenu | null>(null);
@@ -340,9 +341,22 @@ const AdminMenuManagement: React.FC = () => {
}; };
// 메뉴 삭제 모달 열기 // 메뉴 삭제 모달 열기
const handleDeleteClick = (menu: AdminMenu) => { const handleDeleteClick = async (menu: AdminMenu) => {
if (!menu.adminMenuSeq) return;
try {
// 하위 메뉴 존재 여부 확인
const childMenusResponse = await getAdminMenuListByParentSeq(menu.adminMenuSeq);
setHasChildMenus(childMenusResponse.totalContent > 0);
setSelectedMenu(menu); setSelectedMenu(menu);
setDeleteModalVisible(true); setDeleteModalVisible(true);
} catch (error) {
console.error('하위 메뉴 확인 실패:', error);
// 에러 발생 시에도 모달은 열되, 삭제 불가로 처리
setHasChildMenus(true);
setSelectedMenu(menu);
setDeleteModalVisible(true);
}
}; };
// 입력 필드 변경 처리 // 입력 필드 변경 처리
@@ -415,19 +429,11 @@ const AdminMenuManagement: React.FC = () => {
<CCard className="mb-4"> <CCard className="mb-4">
<CCardHeader> <CCardHeader>
<strong> </strong> <strong> </strong>
<CButton
color="primary"
size="sm"
className="float-end"
onClick={handleAddClick}
>
<CIcon icon={cilPlus} className="me-1" />
</CButton>
</CCardHeader> </CCardHeader>
<CCardBody> <CCardBody>
{/* 브레드크럼 네비게이션 */} {/* 브레드크럼 네비게이션 */}
<nav aria-label="breadcrumb" className="mb-3"> <div className="d-flex justify-content-between align-items-center mb-3">
<nav aria-label="breadcrumb">
<ol className="breadcrumb mb-0"> <ol className="breadcrumb mb-0">
<li className={`breadcrumb-item ${breadcrumb.length === 0 ? 'active' : ''}`}> <li className={`breadcrumb-item ${breadcrumb.length === 0 ? 'active' : ''}`}>
{breadcrumb.length === 0 ? ( {breadcrumb.length === 0 ? (
@@ -462,16 +468,24 @@ const AdminMenuManagement: React.FC = () => {
))} ))}
</ol> </ol>
</nav> </nav>
<CButton
color="primary"
size="sm"
onClick={handleAddClick}
>
<CIcon icon={cilPlus} className="me-1" />
</CButton>
</div>
<CTable align="middle" className="mb-0 border" hover responsive style={{ tableLayout: 'fixed', minWidth: isCompact ? '400px' : '650px' }}> <CTable align="middle" className="mb-0 border" hover responsive style={{ tableLayout: 'fixed', minWidth: isCompact ? 'auto' : '650px' }}>
<CTableHead className="text-nowrap"> <CTableHead className="text-nowrap">
<CTableRow> <CTableRow>
<CTableHeaderCell className="bg-body-tertiary text-center" style={{ width: '80px' }}> </CTableHeaderCell> <CTableHeaderCell className="bg-body-tertiary text-center" style={{ width: '70px' }}></CTableHeaderCell>
{!isCompact && ( {!isCompact && (
<CTableHeaderCell className="bg-body-tertiary text-center" style={{ width: '60px' }}></CTableHeaderCell> <CTableHeaderCell className="bg-body-tertiary text-center" style={{ width: '60px' }}></CTableHeaderCell>
)} )}
<CTableHeaderCell className="bg-body-tertiary text-center" style={{ width: '180px' }}> </CTableHeaderCell> <CTableHeaderCell className="bg-body-tertiary text-center" style={{ width: isCompact ? 'auto' : '180px' }}> </CTableHeaderCell>
<CTableHeaderCell className="bg-body-tertiary text-center" style={{ width: '70px' }}></CTableHeaderCell>
{!isCompact && ( {!isCompact && (
<CTableHeaderCell className="bg-body-tertiary text-center" style={{ width: 'auto' }}>URL</CTableHeaderCell> <CTableHeaderCell className="bg-body-tertiary text-center" style={{ width: 'auto' }}>URL</CTableHeaderCell>
)} )}
@@ -481,22 +495,20 @@ const AdminMenuManagement: React.FC = () => {
<CTableBody style={{ minHeight: '200px' }}> <CTableBody style={{ minHeight: '200px' }}>
{loading ? ( {loading ? (
<CTableRow> <CTableRow>
<CTableDataCell colSpan={isCompact ? 4 : 6} className="text-center py-5"> <CTableDataCell colSpan={isCompact ? 3 : 5} className="text-center py-5">
... ...
</CTableDataCell> </CTableDataCell>
</CTableRow> </CTableRow>
) : menuList.length === 0 ? ( ) : menuList.length === 0 ? (
<CTableRow> <CTableRow>
<CTableDataCell colSpan={isCompact ? 4 : 6} className="text-center"> <CTableDataCell colSpan={isCompact ? 3 : 5} className="text-center">
. .
</CTableDataCell> </CTableDataCell>
</CTableRow> </CTableRow>
) : ( ) : (
menuList.map((menu) => ( menuList.map((menu) => (
<CTableRow key={menu.adminMenuSeq}> <CTableRow key={menu.adminMenuSeq}>
<CTableDataCell className="text-center"> <CTableDataCell className="text-center">{menu.menuOrder}</CTableDataCell>
<div className="fw-semibold">{menu.adminMenuSeq}</div>
</CTableDataCell>
{!isCompact && ( {!isCompact && (
<CTableDataCell className="text-center"> <CTableDataCell className="text-center">
{menu.iconName && getIconByName(menu.iconName) ? ( {menu.iconName && getIconByName(menu.iconName) ? (
@@ -525,7 +537,6 @@ const AdminMenuManagement: React.FC = () => {
</a> </a>
</div> </div>
</CTableDataCell> </CTableDataCell>
<CTableDataCell className="text-center">{menu.menuOrder}</CTableDataCell>
{!isCompact && ( {!isCompact && (
<CTableDataCell className="text-center"> <CTableDataCell className="text-center">
<div <div
@@ -760,19 +771,34 @@ const AdminMenuManagement: React.FC = () => {
<CModalTitle> </CModalTitle> <CModalTitle> </CModalTitle>
</CModalHeader> </CModalHeader>
<CModalBody> <CModalBody>
<strong>{selectedMenu?.menuName}</strong> ? {hasChildMenus ? (
<br /> <>
<small className="text-danger"> <div className="text-danger mb-2">
. . <CIcon icon={cilWarning} className="me-2" />
<strong> .</strong>
</div>
<p>
<strong>{selectedMenu?.menuName}</strong> .
</p>
<small className="text-muted">
.
</small> </small>
</>
) : (
<>
<strong>{selectedMenu?.menuName}</strong> ?
</>
)}
</CModalBody> </CModalBody>
<CModalFooter> <CModalFooter>
<CButton color="secondary" onClick={() => setDeleteModalVisible(false)}> <CButton color="secondary" onClick={() => setDeleteModalVisible(false)}>
{hasChildMenus ? '닫기' : '취소'}
</CButton> </CButton>
{!hasChildMenus && (
<CButton color="danger" onClick={handleDelete}> <CButton color="danger" onClick={handleDelete}>
</CButton> </CButton>
)}
</CModalFooter> </CModalFooter>
</CModal> </CModal>
</> </>