Files
sam-react-prod/src/components/quality/InspectionManagement/documents/InspectionReportModal.tsx
유병철 dc0ce471aa feat(WEB): 품질검사 기능 대폭 확장 및 검사입력 모달 추가
품질검사관리:
- InspectionCreate 생성 폼 대폭 개선 (+269줄)
- InspectionDetail 상세 페이지 확장 (+424줄)
- InspectionReportModal 검사성적서 모달 기능 강화
- InspectionReportDocument 문서 구조 개선
- ProductInspectionInputModal 제품검사 입력 모달 신규 추가
- types, mockData, actions 확장

자재입고:
- ReceivingDetail 수입검사 연동 기능 추가
- ImportInspectionInputModal 수입검사 입력 모달 신규 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 23:04:53 +09:00

170 lines
4.9 KiB
TypeScript

'use client';
/**
* 제품검사성적서 모달 (읽기전용)
* DocumentViewer를 사용하여 문서 표시 + 인쇄/PDF 기능 제공
* 검사 입력은 별도 ProductInspectionInputModal에서 진행
*
* 페이지네이션: 층(orderItem)별로 검사성적서 표시
*/
import { useState, useCallback, useMemo, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import { DocumentViewer } from '@/components/document-system';
import { InspectionReportDocument } from './InspectionReportDocument';
import type {
InspectionReportDocument as InspectionReportDocumentType,
OrderSettingItem,
ProductInspection
} from '../types';
import { buildReportDocumentDataForItem } from '../mockData';
interface InspectionReportModalProps {
open: boolean;
onOpenChange: (open: boolean) => void;
data: InspectionReportDocumentType | null;
/** 페이지네이션용: 원본 inspection 데이터 */
inspection?: ProductInspection | null;
/** 페이지네이션용: orderItems (수정 모드에서는 formData.orderItems) */
orderItems?: OrderSettingItem[];
}
export function InspectionReportModal({
open,
onOpenChange,
data,
inspection,
orderItems,
}: InspectionReportModalProps) {
const [currentPage, setCurrentPage] = useState(1);
const [inputPage, setInputPage] = useState('1');
// 총 페이지 수 (orderItems가 있으면 그 길이, 아니면 1)
const totalPages = useMemo(() => {
if (orderItems && orderItems.length > 0) {
return orderItems.length;
}
return 1;
}, [orderItems]);
// 모달 열릴 때 페이지 초기화
useEffect(() => {
if (open) {
setCurrentPage(1);
setInputPage('1');
}
}, [open]);
// 현재 페이지에 해당하는 문서 데이터
const currentData = useMemo(() => {
// 페이지네이션이 가능한 경우 (inspection과 orderItems 모두 있음)
if (inspection && orderItems && orderItems.length > 0) {
const currentItem = orderItems[currentPage - 1];
if (currentItem) {
return buildReportDocumentDataForItem(inspection, currentItem);
}
}
// 기본: data prop 사용
return data;
}, [inspection, orderItems, currentPage, data]);
// 이전 페이지
const handlePrevPage = useCallback(() => {
if (currentPage > 1) {
const newPage = currentPage - 1;
setCurrentPage(newPage);
setInputPage(String(newPage));
}
}, [currentPage]);
// 다음 페이지
const handleNextPage = useCallback(() => {
if (currentPage < totalPages) {
const newPage = currentPage + 1;
setCurrentPage(newPage);
setInputPage(String(newPage));
}
}, [currentPage, totalPages]);
// 페이지 입력 후 이동
const handleGoToPage = useCallback(() => {
const pageNum = parseInt(inputPage, 10);
if (!isNaN(pageNum) && pageNum >= 1 && pageNum <= totalPages) {
setCurrentPage(pageNum);
} else {
// 잘못된 입력 → 현재 페이지로 복원
setInputPage(String(currentPage));
}
}, [inputPage, totalPages, currentPage]);
// 엔터키로 이동
const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
handleGoToPage();
}
}, [handleGoToPage]);
if (!currentData) return null;
// 페이지네이션 UI 컴포넌트
const paginationUI = totalPages > 1 ? (
<div className="flex items-center justify-center gap-2 py-3 border-t bg-gray-100 print:hidden">
<Button
variant="outline"
size="sm"
onClick={handlePrevPage}
disabled={currentPage <= 1}
className="h-8"
>
<ChevronLeft className="w-4 h-4 mr-1" />
</Button>
<div className="flex items-center gap-2">
<Input
value={inputPage}
onChange={(e) => setInputPage(e.target.value)}
onKeyDown={handleKeyDown}
className="w-14 h-8 text-center"
/>
<span className="text-sm text-muted-foreground">/ {totalPages}</span>
</div>
<Button
variant="outline"
size="sm"
onClick={handleGoToPage}
className="h-8"
>
</Button>
<Button
variant="outline"
size="sm"
onClick={handleNextPage}
disabled={currentPage >= totalPages}
className="h-8"
>
<ChevronRight className="w-4 h-4 ml-1" />
</Button>
</div>
) : null;
return (
<DocumentViewer
title="제품검사성적서"
preset="readonly"
open={open}
onOpenChange={onOpenChange}
pdfMeta={{
documentNumber: currentData.documentNumber,
createdDate: currentData.createdDate,
}}
toolbarExtra={paginationUI}
>
<InspectionReportDocument data={currentData} />
</DocumentViewer>
);
}