Files
sam-react-prod/src/components/material/ReceivingManagement/ReceivingProcessDialog.tsx

227 lines
7.4 KiB
TypeScript
Raw Normal View History

'use client';
/**
*
* -
* - LOT*, LOT, *, *
* -
*/
import { useState, useCallback } from 'react';
import { Download } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { generateLotNo } from './mockData';
import type { ReceivingDetail } from './types';
interface Props {
open: boolean;
onOpenChange: (open: boolean) => void;
detail: ReceivingDetail;
onComplete: (lotNo: string) => void;
}
export function ReceivingProcessDialog({ open, onOpenChange, detail, onComplete }: Props) {
// 폼 데이터
const [receivingLot, setReceivingLot] = useState(() => generateLotNo());
const [supplierLot, setSupplierLot] = useState('');
const [receivingQty, setReceivingQty] = useState<string>(detail.orderQty.toString());
const [receivingLocation, setReceivingLocation] = useState('');
const [remark, setRemark] = useState('');
// 유효성 검사 에러
const [validationErrors, setValidationErrors] = useState<string[]>([]);
// 유효성 검사
const validateForm = useCallback((): boolean => {
const errors: string[] = [];
if (!receivingLot.trim()) {
errors.push('입고LOT는 필수 입력 항목입니다.');
}
if (!receivingQty.trim() || isNaN(Number(receivingQty)) || Number(receivingQty) <= 0) {
errors.push('입고수량은 필수 입력 항목입니다. 유효한 숫자를 입력해주세요.');
}
if (!receivingLocation.trim()) {
errors.push('입고위치는 필수 입력 항목입니다.');
}
setValidationErrors(errors);
return errors.length === 0;
}, [receivingLot, receivingQty, receivingLocation]);
// 입고 처리
const handleSubmit = useCallback(() => {
if (!validateForm()) {
return;
}
// TODO: API 호출
console.log('입고 처리:', {
detailId: detail.id,
receivingLot,
supplierLot,
receivingQty: Number(receivingQty),
receivingLocation,
remark,
});
onComplete(receivingLot);
}, [validateForm, detail.id, receivingLot, supplierLot, receivingQty, receivingLocation, remark, onComplete]);
// 취소
const handleCancel = useCallback(() => {
onOpenChange(false);
}, [onOpenChange]);
// 다이얼로그 닫힐 때 상태 초기화
const handleOpenChange = useCallback(
(newOpen: boolean) => {
if (!newOpen) {
setValidationErrors([]);
}
onOpenChange(newOpen);
},
[onOpenChange]
);
return (
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogContent className="max-w-md">
<DialogHeader>
<DialogTitle> </DialogTitle>
</DialogHeader>
<div className="space-y-6 mt-4">
{/* 발주 정보 요약 */}
<div className="grid grid-cols-2 gap-4 text-sm">
<div>
<span className="text-muted-foreground">:</span>{' '}
<span className="font-medium">{detail.orderNo}</span>
</div>
<div>
<span className="text-muted-foreground">:</span>{' '}
<span className="font-medium">{detail.supplier}</span>
</div>
<div>
<span className="text-muted-foreground">:</span>{' '}
<span className="font-medium">{detail.itemName}</span>
</div>
<div>
<span className="text-muted-foreground">:</span>{' '}
<span className="font-medium">{detail.orderQty} {detail.orderUnit}</span>
</div>
</div>
{/* Validation 에러 표시 */}
{validationErrors.length > 0 && (
<Alert className="bg-red-50 border-red-200">
<AlertDescription className="text-red-900">
<div className="flex items-start gap-2">
<span className="text-lg"></span>
<div className="flex-1">
<strong className="block mb-2">
({validationErrors.length} )
</strong>
<ul className="space-y-1 text-sm">
{validationErrors.map((error, index) => (
<li key={index} className="flex items-start gap-1">
<span></span>
<span>{error}</span>
</li>
))}
</ul>
</div>
</div>
</AlertDescription>
</Alert>
)}
{/* 입력 필드 */}
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label className="text-sm">
LOT <span className="text-red-500">*</span>
</Label>
<Input
value={receivingLot}
onChange={(e) => {
setReceivingLot(e.target.value);
setValidationErrors([]);
}}
placeholder="예: 251223-41"
/>
</div>
<div className="space-y-2">
<Label className="text-sm text-muted-foreground">LOT</Label>
<Input
value={supplierLot}
onChange={(e) => setSupplierLot(e.target.value)}
placeholder="예: 2402944"
/>
</div>
<div className="space-y-2">
<Label className="text-sm">
<span className="text-red-500">*</span>
</Label>
<Input
type="number"
value={receivingQty}
onChange={(e) => {
setReceivingQty(e.target.value);
setValidationErrors([]);
}}
placeholder="수량 입력"
/>
</div>
<div className="space-y-2">
<Label className="text-sm">
<span className="text-red-500">*</span>
</Label>
<Input
value={receivingLocation}
onChange={(e) => {
setReceivingLocation(e.target.value);
setValidationErrors([]);
}}
placeholder="예: A-01"
/>
</div>
</div>
{/* 비고 */}
<div className="space-y-2">
<Label className="text-sm text-muted-foreground"></Label>
<Textarea
value={remark}
onChange={(e) => setRemark(e.target.value)}
placeholder="특이사항 입력"
rows={3}
/>
</div>
</div>
{/* 버튼 영역 */}
<div className="flex justify-end gap-2 mt-6 pt-4 border-t">
<Button variant="outline" onClick={handleCancel}>
</Button>
<Button onClick={handleSubmit}>
</Button>
</div>
</DialogContent>
</Dialog>
);
}