feat: 입고 상세 업체 제공 성적서 파일 업로드 기능 적용

- 기존 정적 플레이스홀더를 FileDropzone 공통 컴포넌트로 교체
- 드래그앤드롭 및 클릭 파일 선택 지원
- 파일 선택 후 파일명/크기 표시 및 삭제 기능

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
유병철
2026-01-29 14:00:24 +09:00
parent 44353c09a0
commit e64d22e2f6

View File

@@ -16,7 +16,8 @@
import { useState, useCallback, useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { Upload, FileText } from 'lucide-react';
import { FileText, X } from 'lucide-react';
import { FileDropzone } from '@/components/ui/file-dropzone';
import { InspectionModalV2 } from '@/app/[locale]/(protected)/quality/qms/components/InspectionModalV2';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
@@ -79,6 +80,9 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) {
// 폼 데이터 (등록/수정 모드용)
const [formData, setFormData] = useState<Partial<ReceivingDetailType>>(INITIAL_FORM_DATA);
// 업로드된 파일 상태 (File 객체)
const [uploadedFile, setUploadedFile] = useState<File | null>(null);
// 수입검사 성적서 모달 상태
const [isInspectionModalOpen, setIsInspectionModalOpen] = useState(false);
@@ -403,18 +407,53 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) {
{/* 업체 제공 성적서 자료 - 파일 업로드 */}
<div className="mt-4">
<Label className="text-sm text-muted-foreground"> </Label>
<div className="mt-1.5 px-4 py-8 border-2 border-dashed rounded-md bg-gray-50 hover:bg-gray-100 cursor-pointer transition-colors">
<div className="flex flex-col items-center justify-center gap-2 text-sm text-muted-foreground">
<Upload className="w-8 h-8 text-gray-400" />
<span> , .</span>
</div>
<div className="mt-1.5">
{uploadedFile || formData.certificateFileName ? (
<div className="flex items-center gap-3 px-4 py-3 border rounded-md bg-gray-50">
<FileText className="w-5 h-5 text-blue-500 shrink-0" />
<span className="text-sm truncate flex-1">
{uploadedFile?.name || formData.certificateFileName}
</span>
{uploadedFile && (
<span className="text-xs text-muted-foreground shrink-0">
{(uploadedFile.size / (1024 * 1024)).toFixed(1)}MB
</span>
)}
<button
type="button"
onClick={() => {
setUploadedFile(null);
handleInputChange('certificateFile', undefined);
handleInputChange('certificateFileName', undefined);
}}
className="p-1 hover:bg-gray-200 rounded shrink-0"
>
<X className="w-4 h-4 text-gray-500" />
</button>
</div>
) : (
<FileDropzone
onFilesSelect={(files) => {
const file = files[0];
if (file) {
setUploadedFile(file);
handleInputChange('certificateFileName', file.name);
}
}}
accept=".pdf,.jpg,.jpeg,.png,.doc,.docx,.xls,.xlsx"
maxSize={20}
compact
title="클릭하여 파일을 찾거나, 마우스로 파일을 끌어오세요"
description="PDF, 이미지, 문서 파일 (최대 20MB)"
/>
)}
</div>
</div>
</CardContent>
</Card>
</div>
);
}, [formData]);
}, [formData, uploadedFile]);
// ===== 커스텀 헤더 액션 (view/edit 모드) =====
const customHeaderActions = (isViewMode || isEditMode) && detail ? (