From f71a84f06dd8f22e2ef826d9f03efbe16460cc15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B6=8C=ED=98=81=EC=84=B1?= Date: Mon, 26 Jan 2026 22:04:19 +0900 Subject: [PATCH] =?UTF-8?q?refactor(WEB):=20=EA=B2=AC=EC=A0=81=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EB=AA=A9=EB=A1=9D=20=ED=8E=98=EC=9D=B4=EC=A7=80=20?= =?UTF-8?q?V2=20URL=20=ED=8C=A8=ED=84=B4=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 목록 페이지에서 V1 등록 로직 제거 - ?mode=new → /new 리다이렉트 처리 (V1 호환) - QuoteManagementClient 링크 V2 패턴으로 변경 - 견적 등록: ?mode=new → /new - 상세 보기: ?mode=view 제거 (기본 view) - DevToolbar test URL → V2 URL로 업데이트 --- .../sales/quote-management/page.tsx | 67 +++++++------------ src/components/dev/DevToolbar.tsx | 11 ++- .../quotes/QuoteManagementClient.tsx | 4 +- 3 files changed, 32 insertions(+), 50 deletions(-) diff --git a/src/app/[locale]/(protected)/sales/quote-management/page.tsx b/src/app/[locale]/(protected)/sales/quote-management/page.tsx index b4d29fa3..a9cd884c 100644 --- a/src/app/[locale]/(protected)/sales/quote-management/page.tsx +++ b/src/app/[locale]/(protected)/sales/quote-management/page.tsx @@ -1,15 +1,19 @@ 'use client'; /** - * 견적관리 페이지 (Client Component) + * 견적관리 목록 페이지 + * + * V2 URL 패턴: + * - 목록: /sales/quote-management + * - 등록: /sales/quote-management/new + * - 상세: /sales/quote-management/[id] + * - 수정: /sales/quote-management/[id]?mode=edit */ import { useEffect, useState } from 'react'; import { useSearchParams, useRouter } from 'next/navigation'; import { QuoteManagementClient } from '@/components/quotes/QuoteManagementClient'; -import { QuoteRegistration, QuoteFormData } from '@/components/quotes/QuoteRegistration'; -import { getQuotes, createQuote, transformFormDataToApi } from '@/components/quotes'; -import { toast } from 'sonner'; +import { getQuotes } from '@/components/quotes'; const DEFAULT_PAGINATION = { currentPage: 1, @@ -26,48 +30,29 @@ export default function QuoteManagementPage() { const [data, setData] = useState>['data']>([]); const [pagination, setPagination] = useState(DEFAULT_PAGINATION); const [isLoading, setIsLoading] = useState(true); - const [isSaving, setIsSaving] = useState(false); + // V1 호환: ?mode=new → /new 리다이렉트 useEffect(() => { - if (mode !== 'new') { - getQuotes({ perPage: 100 }) - .then(result => { - setData(result.data); - setPagination(result.pagination); - }) - .finally(() => setIsLoading(false)); - } else { - setIsLoading(false); + if (mode === 'new') { + router.replace('/sales/quote-management/new'); + return; } - }, [mode]); + getQuotes({ perPage: 100 }) + .then(result => { + setData(result.data); + setPagination(result.pagination); + }) + .finally(() => setIsLoading(false)); + }, [mode, router]); + + // 리다이렉트 중이면 로딩 표시 if (mode === 'new') { - const handleBack = () => { - router.push('/sales/quote-management'); - }; - - const handleSave = async (formData: QuoteFormData): Promise<{ success: boolean; error?: string }> => { - if (isSaving) return { success: false, error: '저장 중입니다.' }; - setIsSaving(true); - - try { - const apiData = transformFormDataToApi(formData); - const result = await createQuote(apiData as any); - - if (result.success && result.data) { - router.push(`/sales/quote-management/${result.data.id}`); - return { success: true }; - } else { - return { success: false, error: result.error || '견적 등록에 실패했습니다.' }; - } - } catch (error) { - return { success: false, error: '견적 등록에 실패했습니다.' }; - } finally { - setIsSaving(false); - } - }; - - return ; + return ( +
+
리다이렉트 중...
+
+ ); } if (isLoading) { diff --git a/src/components/dev/DevToolbar.tsx b/src/components/dev/DevToolbar.tsx index a565a88b..83a01456 100644 --- a/src/components/dev/DevToolbar.tsx +++ b/src/components/dev/DevToolbar.tsx @@ -42,11 +42,9 @@ import { useDevFillContext, type DevFillPageType } from './DevFillContext'; // 페이지 경로와 타입 매핑 (pathname만으로 매칭되는 패턴) const PAGE_PATTERNS: { pattern: RegExp; type: DevFillPageType; label: string }[] = [ - // 판매/생산 플로우 - { pattern: /\/quote-management\/test-new/, type: 'quoteV2', label: '견적V2' }, - { pattern: /\/quote-management\/test\/\d+/, type: 'quoteV2', label: '견적V2' }, - { pattern: /\/quote-management\/new/, type: 'quote', label: '견적' }, - { pattern: /\/quote-management\/\d+\/edit/, type: 'quote', label: '견적' }, + // 판매/생산 플로우 (V2 URL 패턴 적용) + { pattern: /\/quote-management\/new$/, type: 'quoteV2', label: '견적V2' }, + { pattern: /\/quote-management\/\d+$/, type: 'quoteV2', label: '견적V2' }, { pattern: /\/order-management-sales\/new/, type: 'order', label: '수주' }, { pattern: /\/order-management-sales\/\d+\/edit/, type: 'order', label: '수주' }, { pattern: /\/work-orders\/create/, type: 'workOrder', label: '작업지시' }, @@ -73,8 +71,7 @@ const MODE_NEW_PAGES: { pattern: RegExp; type: DevFillPageType; label: string }[ // 플로우 단계 정의 const FLOW_STEPS: { type: DevFillPageType; label: string; icon: typeof FileText; path: string }[] = [ - { type: 'quoteV2', label: '견적V2', icon: FileText, path: '/sales/quote-management/test-new' }, - { type: 'quote', label: '견적', icon: FileText, path: '/sales/quote-management/new' }, + { type: 'quoteV2', label: '견적', icon: FileText, path: '/sales/quote-management/new' }, { type: 'order', label: '수주', icon: ClipboardList, path: '/sales/order-management-sales?mode=new' }, { type: 'workOrder', label: '작업지시', icon: Wrench, path: '/production/work-orders/create' }, { type: 'workOrderComplete', label: '완료', icon: CheckCircle2, path: '' }, // 상세 페이지에서 처리 diff --git a/src/components/quotes/QuoteManagementClient.tsx b/src/components/quotes/QuoteManagementClient.tsx index 90067739..5a8eeeba 100644 --- a/src/components/quotes/QuoteManagementClient.tsx +++ b/src/components/quotes/QuoteManagementClient.tsx @@ -79,7 +79,7 @@ export function QuoteManagementClient({ // ===== 핸들러 ===== const handleView = useCallback((quote: Quote) => { - router.push(`/sales/quote-management/${quote.id}?mode=view`); + router.push(`/sales/quote-management/${quote.id}`); }, [router]); const handleEdit = useCallback((quote: Quote) => { @@ -358,7 +358,7 @@ export function QuoteManagementClient({ headerActions: () => (