From 5a00979506d629fc9c2c546e090638a876c72bfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Sat, 21 Mar 2026 21:20:49 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20[=EC=9E=AC=EA=B3=A0=EC=83=9D=EC=82=B0]?= =?UTF-8?q?=20=EB=B3=B5=EC=82=AC=20=EB=B2=84=ED=8A=BC=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20+=20STOCK=20LOT=20=EB=B2=88=ED=98=B8=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../(protected)/sales/stocks/page.tsx | 47 +++++++++++++++++++ src/components/stocks/BendingLotForm.tsx | 10 +++- .../stocks/StockProductionDetail.tsx | 13 ++++- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/app/[locale]/(protected)/sales/stocks/page.tsx b/src/app/[locale]/(protected)/sales/stocks/page.tsx index f439002a..4b5a09f3 100644 --- a/src/app/[locale]/(protected)/sales/stocks/page.tsx +++ b/src/app/[locale]/(protected)/sales/stocks/page.tsx @@ -5,17 +5,64 @@ * * - 기본: 목록 (StockProductionList) * - ?mode=new: 등록 (BendingLotForm — 절곡품 LOT 방식) + * - ?mode=new©From={id}: 복사 등록 (기존 데이터 기반) */ +import { useState, useEffect } from 'react'; import { useSearchParams } from 'next/navigation'; +import { Loader2 } from 'lucide-react'; +import { toast } from 'sonner'; import { StockProductionList } from '@/components/stocks/StockProductionList'; import { BendingLotForm } from '@/components/stocks/BendingLotForm'; +import { getStockOrderById, type StockOrder } from '@/components/stocks/actions'; + +function CopyStockContent({ copyFromId }: { copyFromId: string }) { + const [order, setOrder] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function load() { + try { + const result = await getStockOrderById(copyFromId); + if (result.__authError) { + toast.error('인증이 만료되었습니다.'); + return; + } + if (result.success && result.data) { + setOrder(result.data); + } else { + toast.error(result.error || '복사할 데이터를 불러오는데 실패했습니다.'); + } + } finally { + setLoading(false); + } + } + load(); + }, [copyFromId]); + + if (loading) { + return ( +
+
+ +

데이터를 불러오는 중...

+
+
+ ); + } + + return ; +} export default function StocksPage() { const searchParams = useSearchParams(); const mode = searchParams.get('mode'); + const copyFrom = searchParams.get('copyFrom'); if (mode === 'new') { + if (copyFrom) { + return ; + } return ; } diff --git a/src/components/stocks/BendingLotForm.tsx b/src/components/stocks/BendingLotForm.tsx index 86637542..b558336c 100644 --- a/src/components/stocks/BendingLotForm.tsx +++ b/src/components/stocks/BendingLotForm.tsx @@ -240,11 +240,13 @@ export function BendingLotForm({ initialData, isEditMode = false }: BendingLotFo const locale = (params.locale as string) || 'ko'; const basePath = `/${locale}/sales/stocks`; + const isCopyMode = !isEditMode && !!initialData; + const [form, setForm] = useState(() => { if (initialData?.bendingLot) { const bl = initialData.bendingLot; return { - regDate: initialData.regDate || getInitialForm().regDate, + regDate: isCopyMode ? getInitialForm().regDate : (initialData.regDate || getInitialForm().regDate), prodCode: bl.prodCode || '', specCode: bl.specCode || '', lengthCode: bl.lengthCode || '', @@ -264,7 +266,11 @@ export function BendingLotForm({ initialData, isEditMode = false }: BendingLotFo const [rawLotModalOpen, setRawLotModalOpen] = useState(false); const [fabricLotModalOpen, setFabricLotModalOpen] = useState(false); - const config = isEditMode ? bendingEditConfig : bendingCreateConfig; + const config = isEditMode + ? bendingEditConfig + : isCopyMode + ? { ...bendingCreateConfig, description: '기존 재고생산을 복사하여 등록합니다' } + : bendingCreateConfig; // 코드맵 로드 + edit mode 시 초기 품목 매핑 조회 useEffect(() => { diff --git a/src/components/stocks/StockProductionDetail.tsx b/src/components/stocks/StockProductionDetail.tsx index d19d9763..a07dfc96 100644 --- a/src/components/stocks/StockProductionDetail.tsx +++ b/src/components/stocks/StockProductionDetail.tsx @@ -18,8 +18,10 @@ import { MessageSquare, Tag, Layers, + Copy, } from 'lucide-react'; import { toast } from 'sonner'; +import { Button } from '@/components/ui/button'; import { IntegratedDetailTemplate } from '@/components/templates/IntegratedDetailTemplate'; import { FormSection } from '@/components/organisms/FormSection'; import { @@ -257,7 +259,16 @@ export function StockProductionDetail({ orderId }: StockProductionDetailProps) { } return { success: result.success, error: result.error }; }} - headerActions={null} + headerActions={ + + } renderView={(data) => renderViewContent(data as unknown as StockOrder)} />