fix: [material] BOM 트리뷰어 개선 + 입고관리 다이얼로그 보강
This commit is contained in:
@@ -18,6 +18,8 @@ import {
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogDescription,
|
||||
VisuallyHidden,
|
||||
} from '@/components/ui/dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
@@ -668,7 +670,11 @@ export function ImportInspectionInputModal({
|
||||
// 캡처 실패 시 무시 — rendered_html 없이 저장 진행
|
||||
}
|
||||
|
||||
// 5. 저장 API 호출
|
||||
// 5. 저장 API 호출 (rendered_html 500KB 초과 시 제외 — 413 에러 방지)
|
||||
const MAX_HTML_SIZE = 500 * 1024;
|
||||
const safeHtml = renderedHtml && renderedHtml.length <= MAX_HTML_SIZE
|
||||
? renderedHtml : undefined;
|
||||
|
||||
const result = await saveInspectionData({
|
||||
templateId: parseInt(template.templateId),
|
||||
itemId,
|
||||
@@ -677,7 +683,7 @@ export function ImportInspectionInputModal({
|
||||
attachments,
|
||||
receivingId,
|
||||
inspectionResult: overallResult,
|
||||
rendered_html: renderedHtml,
|
||||
rendered_html: safeHtml,
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
@@ -755,6 +761,7 @@ export function ImportInspectionInputModal({
|
||||
<DialogContent className="w-[95vw] max-w-[500px] sm:max-w-[500px] max-h-[90vh] flex flex-col p-0">
|
||||
<DialogHeader className="px-6 pt-6 pb-0 shrink-0">
|
||||
<DialogTitle className="text-lg font-bold">수입검사</DialogTitle>
|
||||
<VisuallyHidden><DialogDescription>수입검사 항목 입력</DialogDescription></VisuallyHidden>
|
||||
</DialogHeader>
|
||||
|
||||
{isLoadingTemplate ? (
|
||||
|
||||
@@ -19,6 +19,8 @@ import {
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogDescription,
|
||||
VisuallyHidden,
|
||||
} from '@/components/ui/dialog';
|
||||
import {
|
||||
Select,
|
||||
@@ -127,6 +129,7 @@ export function InventoryAdjustmentDialog({ open, onOpenChange, onSave }: Props)
|
||||
<DialogContent className="max-w-[95vw] w-[95vw] max-h-[90vh] flex flex-col">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-lg font-semibold">재고 조정</DialogTitle>
|
||||
<VisuallyHidden><DialogDescription>재고 수량 조정</DialogDescription></VisuallyHidden>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex flex-col gap-4 flex-1 min-h-0">
|
||||
|
||||
@@ -67,28 +67,30 @@ interface Props {
|
||||
mode?: 'view' | 'edit' | 'new';
|
||||
}
|
||||
|
||||
// 초기 폼 데이터
|
||||
const INITIAL_FORM_DATA: Partial<ReceivingDetailType> = {
|
||||
materialNo: '',
|
||||
supplierMaterialNo: '',
|
||||
lotNo: '',
|
||||
itemCode: '',
|
||||
itemName: '',
|
||||
specification: '',
|
||||
unit: 'EA',
|
||||
supplier: '',
|
||||
manufacturer: '',
|
||||
receivingQty: undefined,
|
||||
receivingDate: '',
|
||||
createdBy: '',
|
||||
status: 'receiving_pending',
|
||||
remark: '',
|
||||
inspectionDate: '',
|
||||
inspectionResult: '',
|
||||
certificateFile: undefined,
|
||||
certificateFileId: undefined,
|
||||
inventoryAdjustments: [],
|
||||
};
|
||||
// 초기 폼 데이터 (동적 함수 — 세션 사용자 이름 + 오늘 날짜 기본값)
|
||||
function createInitialFormData(): Partial<ReceivingDetailType> {
|
||||
return {
|
||||
materialNo: '',
|
||||
supplierMaterialNo: '',
|
||||
lotNo: '',
|
||||
itemCode: '',
|
||||
itemName: '',
|
||||
specification: '',
|
||||
unit: 'EA',
|
||||
supplier: '',
|
||||
manufacturer: '',
|
||||
receivingQty: undefined,
|
||||
receivingDate: getTodayString(),
|
||||
createdBy: getLoggedInUserName(),
|
||||
status: 'receiving_pending',
|
||||
remark: '',
|
||||
inspectionDate: '',
|
||||
inspectionResult: '',
|
||||
certificateFile: undefined,
|
||||
certificateFileId: undefined,
|
||||
inventoryAdjustments: [],
|
||||
};
|
||||
}
|
||||
|
||||
// localStorage에서 로그인 사용자 정보 가져오기
|
||||
function getLoggedInUser(): { name: string; department: string } {
|
||||
@@ -122,7 +124,7 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// 폼 데이터 (등록/수정 모드용)
|
||||
const [formData, setFormData] = useState<Partial<ReceivingDetailType>>(INITIAL_FORM_DATA);
|
||||
const [formData, setFormData] = useState<Partial<ReceivingDetailType>>(createInitialFormData);
|
||||
|
||||
// 업로드된 파일 상태 (File 객체)
|
||||
const [uploadedFile, setUploadedFile] = useState<File | null>(null);
|
||||
@@ -275,8 +277,14 @@ export function ReceivingDetail({ id, mode = 'view' }: Props) {
|
||||
const result = await createReceiving(saveData);
|
||||
if (result.success) {
|
||||
toast.success('입고가 등록되었습니다.');
|
||||
router.push('/ko/material/receiving-management');
|
||||
return { success: true };
|
||||
const newId = result.data?.id;
|
||||
if (newId) {
|
||||
router.push(`/ko/material/receiving-management/${newId}?mode=view`);
|
||||
} else {
|
||||
router.push('/ko/material/receiving-management');
|
||||
}
|
||||
// 커스텀 네비게이션 처리: error='' → 템플릿의 navigateToList() 호출 방지
|
||||
return { success: false, error: '' };
|
||||
} else {
|
||||
toast.error(result.error || '등록에 실패했습니다.');
|
||||
return { success: false, error: result.error };
|
||||
|
||||
@@ -19,6 +19,8 @@ import {
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogDescription,
|
||||
VisuallyHidden,
|
||||
} from '@/components/ui/dialog';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import type { ReceivingDetail, ReceivingProcessFormData } from './types';
|
||||
@@ -99,6 +101,7 @@ export function ReceivingProcessDialog({ open, onOpenChange, detail, onComplete
|
||||
<DialogContent className="max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle>입고 처리</DialogTitle>
|
||||
<VisuallyHidden><DialogDescription>입고 처리 정보 입력</DialogDescription></VisuallyHidden>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-6 mt-4">
|
||||
|
||||
@@ -9,6 +9,9 @@ import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
DialogDescription,
|
||||
VisuallyHidden,
|
||||
} from '@/components/ui/dialog';
|
||||
|
||||
interface Props {
|
||||
@@ -27,6 +30,10 @@ export function SuccessDialog({ open, type, lotNo, onClose }: Props) {
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={(newOpen) => !newOpen && onClose()}>
|
||||
<DialogContent className="max-w-sm">
|
||||
<VisuallyHidden>
|
||||
<DialogTitle>처리 완료</DialogTitle>
|
||||
<DialogDescription>처리 결과 안내</DialogDescription>
|
||||
</VisuallyHidden>
|
||||
<div className="flex flex-col items-center text-center py-6 space-y-4">
|
||||
<div className="w-16 h-16 rounded-full bg-green-100 flex items-center justify-center">
|
||||
<CheckCircle2 className="w-10 h-10 text-green-600" />
|
||||
|
||||
Reference in New Issue
Block a user