feat(WEB): 전체 페이지 ?mode= URL 네비게이션 패턴 적용

- 등록(?mode=new), 상세(?mode=view), 수정(?mode=edit) URL 패턴 일괄 적용
- 중복 패턴 제거: /edit?mode=edit → ?mode=edit (16개 파일)
- 제목 일관성: {기능} 등록/상세/수정 패턴 적용
- 검수 체크리스트 문서 추가 (79개 페이지)
- UniversalListPage, IntegratedDetailTemplate 공통 컴포넌트 개선

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-01-25 12:27:43 +09:00
parent 72f1accbe4
commit f6551c7e8b
162 changed files with 2907 additions and 480 deletions

View File

@@ -117,6 +117,11 @@ function IntegratedDetailTemplateInner<T extends Record<string, unknown>>(
const isCreateMode = mode === 'create';
const isEditMode = mode === 'edit';
// ===== mode prop 변경 시 내부 state 동기화 =====
useEffect(() => {
setMode(initialMode);
}, [initialMode]);
// ===== 초기 데이터 설정 =====
useEffect(() => {
if (initialData) {
@@ -298,10 +303,14 @@ function IntegratedDetailTemplateInner<T extends Record<string, unknown>>(
onEditProp();
return;
}
// 기본 동작: 내부 모드 변경
// 기본 동작: 내부 모드 변경 + URL 변경
setMode('edit');
onModeChange?.('edit');
}, [onEditProp, onModeChange]);
// URL에 ?mode=edit 추가
if (itemId) {
router.push(`/${locale}${config.basePath}/${itemId}?mode=edit`);
}
}, [onEditProp, onModeChange, router, locale, config.basePath, itemId]);
// ===== 액션 설정 =====
const actions = config.actions || {};
@@ -424,11 +433,12 @@ function IntegratedDetailTemplateInner<T extends Record<string, unknown>>(
}
// ===== Form 모드 - 커스텀 렌더러 =====
if (!isViewMode && renderForm) {
// View 모드에서 renderView가 없으면 renderForm으로 폴백 (EmployeeForm 등 renderForm만 사용하는 컴포넌트 지원)
if (renderForm && (!isViewMode || !renderView)) {
return (
<PageLayout>
<PageHeader
title={isCreateMode ? `${config.title} 등록` : `${config.title} 수정`}
title={isCreateMode ? `${config.title} 등록` : isViewMode ? config.title : `${config.title} 수정`}
description={config.description}
icon={config.icon}
actions={isTopButtons ? renderActionButtons() : undefined}
@@ -443,6 +453,16 @@ function IntegratedDetailTemplateInner<T extends Record<string, unknown>>(
{afterContent}
{/* 버튼 영역 - 하단 배치 시만 */}
{!isTopButtons && renderActionButtons('mt-6')}
{/* View 모드에서 renderForm 폴백 시 삭제 다이얼로그 필요 */}
{isViewMode && (
<DeleteConfirmDialog
open={showDeleteDialog}
onOpenChange={setShowDeleteDialog}
onConfirm={handleConfirmDelete}
title={deleteConfirm.title}
description={deleteConfirm.description}
/>
)}
</PageLayout>
);
}