Files
sam-react-prod/src/components/process-management/ProcessDetailClientV2.tsx
권혁성 6d8116713f feat(WEB): 공정관리 품목 제거 기능 및 리팩토링
- ProcessDetail: 개별 품목 제거(removeProcessItem) 기능 추가
- ProcessDetail: onProcessUpdate 콜백으로 부모 컴포넌트 동기화
- ProcessDetail: 삭제 다이얼로그 제거, 품목 목록 flatMap 추출 방식 개선
- ProcessForm: 규칙 모달 관련 코드 추가
- RuleModal: UI 개선
- actions.ts: removeProcessItem API 함수 추가
2026-02-09 21:31:00 +09:00

137 lines
3.9 KiB
TypeScript

'use client';
/**
* 공정관리 상세 클라이언트 컴포넌트 V2
*
* 라우팅 구조 변경: /[id], /[id]/edit, /new → /[id]?mode=view|edit, /new
* 기존 ProcessDetail, ProcessForm 컴포넌트 활용
*/
import { useState, useEffect, useCallback } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { ProcessDetail } from './ProcessDetail';
import { ProcessForm } from './ProcessForm';
import { getProcessById } from './actions';
import type { Process } from '@/types/process';
import { DetailPageSkeleton } from '@/components/ui/skeleton';
import { ErrorCard } from '@/components/ui/error-card';
import { toast } from 'sonner';
type DetailMode = 'view' | 'edit' | 'create';
interface ProcessDetailClientV2Props {
processId?: string;
initialMode?: DetailMode;
}
const BASE_PATH = '/ko/master-data/process-management';
export function ProcessDetailClientV2({ processId, initialMode }: ProcessDetailClientV2Props) {
const router = useRouter();
const searchParams = useSearchParams();
// URL 쿼리에서 모드 결정
const modeFromQuery = searchParams.get('mode') as DetailMode | null;
const isNewMode = !processId || processId === 'new';
const [mode, setMode] = useState<DetailMode>(() => {
if (isNewMode) return 'create';
if (initialMode) return initialMode;
if (modeFromQuery === 'edit') return 'edit';
return 'view';
});
const [processData, setProcessData] = useState<Process | null>(null);
const [isLoading, setIsLoading] = useState(!isNewMode);
const [error, setError] = useState<string | null>(null);
// 데이터 로드
useEffect(() => {
const loadData = async () => {
if (isNewMode) {
setIsLoading(false);
return;
}
setIsLoading(true);
setError(null);
try {
const result = await getProcessById(processId!);
if (result.success && result.data) {
setProcessData(result.data);
} else {
setError(result.error || '공정 정보를 찾을 수 없습니다.');
toast.error('공정을 불러오는데 실패했습니다.');
}
} catch (err) {
console.error('공정 조회 실패:', err);
setError('공정 정보를 불러오는 중 오류가 발생했습니다.');
toast.error('공정을 불러오는데 실패했습니다.');
} finally {
setIsLoading(false);
}
};
loadData();
}, [processId, isNewMode]);
// URL 쿼리 변경 감지
useEffect(() => {
if (!isNewMode && modeFromQuery === 'edit') {
setMode('edit');
} else if (!isNewMode && !modeFromQuery) {
setMode('view');
}
}, [modeFromQuery, isNewMode]);
// 로딩 중
if (isLoading) {
return <DetailPageSkeleton sections={1} fieldsPerSection={4} />;
}
// 에러 발생 (view/edit 모드에서)
if (error && !isNewMode) {
return (
<ErrorCard
type="network"
title="공정 정보를 불러올 수 없습니다"
description={error}
tips={[
'해당 공정이 존재하는지 확인해주세요',
'인터넷 연결 상태를 확인해주세요',
'잠시 후 다시 시도해주세요',
]}
homeButtonLabel="목록으로 이동"
homeButtonHref={BASE_PATH}
/>
);
}
// 등록 모드
if (mode === 'create') {
return <ProcessForm mode="create" />;
}
// 수정 모드
if (mode === 'edit' && processData) {
return <ProcessForm mode="edit" initialData={processData} />;
}
// 상세 보기 모드
if (mode === 'view' && processData) {
return <ProcessDetail process={processData} onProcessUpdate={setProcessData} />;
}
// 데이터 없음 (should not reach here)
return (
<ErrorCard
type="not-found"
title="공정을 찾을 수 없습니다"
description="요청하신 공정 정보가 존재하지 않습니다."
homeButtonLabel="목록으로 이동"
homeButtonHref={BASE_PATH}
/>
);
}