erp-platform/ui/src/views/warehouse/components/LotForm.tsx
2025-09-16 00:11:40 +03:00

247 lines
8.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from 'react'
import { useFormik } from 'formik'
import * as Yup from 'yup'
import { FaSave, FaTimes } from 'react-icons/fa'
import { QualityStatusEnum, MmLotNumber, MmUnit, MmMaterial } from '../../../types/mm'
import { BusinessParty } from '../../../types/common'
const validationSchema = Yup.object({
materialId: Yup.string().required('Malzeme seçimi zorunlu'),
lotNumber: Yup.string().required('Lot numarası zorunlu'),
quantity: Yup.number().min(0, "Miktar 0'dan büyük olmalıdır"),
})
interface LotFormProps {
isOpen: boolean
onClose: () => void
onSave: (lot: MmLotNumber) => void
onUpdate?: (lot: MmLotNumber) => void
materials: MmMaterial[]
suppliers?: BusinessParty[]
units?: MmUnit[]
initial?: MmLotNumber | null
mode?: 'create' | 'edit' | 'view'
}
const LotForm: React.FC<LotFormProps> = ({
isOpen,
onClose,
onSave,
onUpdate,
materials,
suppliers = [],
units = [],
initial = null,
mode = 'create',
}) => {
const formik = useFormik({
initialValues: {
materialId: '',
lotNumber: '',
productionDate: '',
expiryDate: '',
quantity: 0,
unitId: 'KG',
supplierId: suppliers.length ? suppliers[0].id : '',
qualityStatus: QualityStatusEnum.Pending,
isActive: true,
},
validationSchema,
onSubmit: async (values) => {
const newLot: MmLotNumber = {
id: (initial && initial.id) || Date.now().toString(),
materialId: values.materialId,
lotNumber: values.lotNumber,
productionDate: values.productionDate ? new Date(values.productionDate) : new Date(),
expiryDate: values.expiryDate ? new Date(values.expiryDate) : undefined,
quantity: Number(values.quantity),
unitId: values.unitId,
supplierId: values.supplierId || undefined,
qualityStatus: values.qualityStatus,
isActive: !!values.isActive,
}
// simulate API
await new Promise((r) => setTimeout(r, 300))
if (mode === 'edit' && onUpdate) {
onUpdate(newLot)
} else {
onSave(newLot)
}
onClose()
},
})
// sync initial values when editing/viewing
React.useEffect(() => {
if (initial) {
const src = initial
formik.setValues({
materialId: src.materialId || '',
lotNumber: src.lotNumber || '',
productionDate: src.productionDate
? new Date(src.productionDate).toISOString().slice(0, 10)
: '',
expiryDate: src.expiryDate ? new Date(src.expiryDate).toISOString().slice(0, 10) : '',
quantity: src.quantity || 0,
unitId: src.unitId || (units.length ? units[0].id : ''),
supplierId: src.supplierId || (suppliers.length ? suppliers[0].id : ''),
qualityStatus: src.qualityStatus || QualityStatusEnum.Pending,
isActive: !!src.isActive,
})
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [initial])
if (!isOpen) return null
return (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<div className="absolute inset-0 bg-black opacity-40" onClick={onClose} />
<div className="relative bg-white rounded-lg shadow-lg w-full max-w-2xl mx-4">
<form onSubmit={formik.handleSubmit} className="space-y-2 p-3">
<div className="flex items-center justify-between p-2 border-b">
<div>
<h2 className="text-2xl font-bold text-gray-900">
{mode === 'create'
? 'Yeni Lot Kaydı'
: mode === 'edit'
? 'Lot Düzenle'
: 'Lot Detayı'}
</h2>
<p className="text-gray-600">
{mode === 'create'
? 'Lot bilgilerini girin'
: mode === 'edit'
? 'Mevcut lot bilgilerini güncelleyin'
: 'Lot bilgileri (sadece gösterim)'}
</p>
</div>
<div className="flex items-center space-x-2">
<button
type="button"
onClick={onClose}
className="px-2.5 py-1 text-sm border rounded-md bg-white hover:bg-gray-50"
>
<FaTimes className="inline mr-1 h-3 w-3" /> Kapat
</button>
{mode !== 'view' && (
<button
type="submit"
className="px-2.5 py-1 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 flex items-center"
>
<FaSave className="inline mr-1 h-3 w-3" /> Kaydet
</button>
)}
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 p-2 gap-x-3 gap-y-2">
<div>
<label className="block text-sm font-medium text-gray-700">Malzeme *</label>
<select
{...formik.getFieldProps('materialId')}
disabled={mode === 'view'}
className="w-full border rounded-md px-2 py-1 text-sm"
>
<option value="">Seçiniz...</option>
{materials.map((m) => (
<option key={m.id} value={m.id}>
{m.code} - {m.name}
</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">Lot Numarası *</label>
<input
type="text"
{...formik.getFieldProps('lotNumber')}
disabled={mode === 'view'}
className="w-full border rounded-md px-2 py-1 text-sm"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">Üretim Tarihi</label>
<input
type="date"
{...formik.getFieldProps('productionDate')}
disabled={mode === 'view'}
className="w-full border rounded-md px-2 py-1 text-sm"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">Son Kullanma Tarihi</label>
<input
type="date"
{...formik.getFieldProps('expiryDate')}
disabled={mode === 'view'}
className="w-full border rounded-md px-2 py-1 text-sm"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">Miktar</label>
<input
type="number"
step="0.01"
{...formik.getFieldProps('quantity')}
disabled={mode === 'view'}
className="w-full border rounded-md px-2 py-1 text-sm"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">Birim</label>
<select
{...formik.getFieldProps('unitId')}
disabled={mode === 'view'}
className="w-full border rounded-md px-2 py-1 text-sm"
>
{units.map((u) => (
<option key={u.id} value={u.id}>
{u.code}
</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">Tedarikçi</label>
<select
{...formik.getFieldProps('supplierId')}
disabled={mode === 'view'}
className="w-full border rounded-md px-2 py-1 text-sm"
>
<option value="">Seçiniz...</option>
{suppliers.map((s) => (
<option key={s.id} value={s.id}>
{s.code} - {s.name}
</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">Kalite Durumu</label>
<select
{...formik.getFieldProps('qualityStatus')}
className="w-full border rounded-md px-2 py-1 text-sm"
>
<option value={QualityStatusEnum.Pending}>Beklemede</option>
<option value={QualityStatusEnum.Approved}>Onaylandı</option>
<option value={QualityStatusEnum.Rejected}>Reddedildi</option>
<option value={QualityStatusEnum.Quarantine}>Karantina</option>
</select>
</div>
</div>
</form>
</div>
</div>
)
}
export default LotForm