feat(WEB): Phase 6 IntegratedDetailTemplate 마이그레이션 완료

Phase 6 마이그레이션 (41개 컴포넌트 완료):
- 건설/시공: 협력업체, 시공관리, 기성관리, 발주관리, 계약관리 등
- 영업: 견적관리(V2), 고객관리(V2), 수주관리
- 회계: 청구관리, 매입관리, 매출관리, 거래처관리, 악성채권 등
- 생산: 작업지시, 검수관리
- 출고: 출하관리
- 자재: 입고관리, 재고현황
- 고객센터: 문의관리, 이벤트관리, 공지관리
- 인사: 직원관리
- 설정: 권한관리

주요 변경사항:
- 34개 xxxConfig.ts 파일 생성 (설정 기반 페이지 구성)
- PageLayout/PageHeader → IntegratedDetailTemplate 통합
- 일관된 타이틀/버튼 영역 (목록, 상세, 수정, 삭제)
- 1112줄 코드 감소 (중복 제거)

프로젝트 공통화 현황 분석 문서 추가:
- 상세 페이지 62%, 목록 페이지 82% 공통화 달성
- 추가 공통화 기회 및 로드맵 정리

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-01-20 15:51:02 +09:00
parent 6f457b28f3
commit 61e3a0ed60
71 changed files with 4743 additions and 4402 deletions

View File

@@ -16,7 +16,6 @@ import {
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import { ContentLoadingSpinner } from '@/components/ui/loading-spinner';
import { ServerErrorPage } from '@/components/common/ServerErrorPage';
import type { Employee, EmployeeFormData } from '@/components/hr/EmployeeManagement/types';
export default function EmployeeDetailPage() {

View File

@@ -1,6 +1,7 @@
/**
* 견적 상세/수정 테스트 페이지 (V2 UI 통합)
*
* IntegratedDetailTemplate 마이그레이션 완료 (2026-01-20)
* 새로운 자동 견적 산출 UI 테스트용
* URL 패턴:
* - /quote-management/test/[id] → 상세 보기 (view)
@@ -10,9 +11,11 @@
"use client";
import { useRouter, useParams, useSearchParams } from "next/navigation";
import { useState, useEffect } from "react";
import { useState, useEffect, useMemo, useCallback } from "react";
import { QuoteRegistrationV2, QuoteFormDataV2, LocationItem } from "@/components/quotes/QuoteRegistrationV2";
import { ContentLoadingSpinner } from "@/components/ui/loading-spinner";
import { IntegratedDetailTemplate } from "@/components/templates/IntegratedDetailTemplate";
import { quoteConfig } from "@/components/quotes/quoteConfig";
import { Badge } from "@/components/ui/badge";
import { toast } from "sonner";
// 테스트용 목업 데이터
@@ -116,12 +119,12 @@ export default function QuoteTestDetailPage() {
loadQuote();
}, [quoteId, router]);
const handleBack = () => {
const handleBack = useCallback(() => {
router.push("/sales/quote-management");
};
}, [router]);
// V2 패턴: 수정 저장 핸들러
const handleSave = async (data: QuoteFormDataV2, saveType: "temporary" | "final") => {
const handleSave = useCallback(async (data: QuoteFormDataV2, saveType: "temporary" | "final") => {
setIsSaving(true);
try {
// TODO: API 연동 시 실제 저장 로직 구현
@@ -142,20 +145,52 @@ export default function QuoteTestDetailPage() {
} finally {
setIsSaving(false);
}
};
}, [router, quoteId]);
if (isLoading) {
return <ContentLoadingSpinner text="견적 정보를 불러오는 중..." />;
}
// 동적 config (모드별 타이틀)
const dynamicConfig = useMemo(() => {
const title = isEditMode ? '견적 수정 (V2 테스트)' : '견적 상세 (V2 테스트)';
return {
...quoteConfig,
title,
};
}, [isEditMode]);
// V2 패턴: mode에 따라 view/edit 렌더링
// 커스텀 헤더 액션 (상태 뱃지)
const customHeaderActions = useMemo(() => {
if (!quote) return null;
return (
<Badge variant={quote.status === "final" ? "default" : quote.status === "temporary" ? "secondary" : "outline"}>
{quote.status === "final" ? "최종저장" : quote.status === "temporary" ? "임시저장" : "작성중"}
</Badge>
);
}, [quote]);
// 폼 콘텐츠 렌더링
const renderFormContent = useCallback(() => {
return (
<QuoteRegistrationV2
mode={isEditMode ? "edit" : "view"}
onBack={handleBack}
onSave={isEditMode ? handleSave : undefined}
initialData={quote}
isLoading={isSaving}
hideHeader={true}
/>
);
}, [isEditMode, handleBack, handleSave, quote, isSaving]);
// IntegratedDetailTemplate 사용
return (
<QuoteRegistrationV2
<IntegratedDetailTemplate
config={dynamicConfig}
mode={isEditMode ? "edit" : "view"}
onBack={handleBack}
onSave={isEditMode ? handleSave : undefined}
initialData={quote}
isLoading={isSaving}
initialData={quote || {}}
itemId={quoteId}
isLoading={isLoading}
headerActions={customHeaderActions}
renderView={() => renderFormContent()}
renderForm={() => renderFormContent()}
/>
);
}