erp-platform/ui/src/views/accounting/components/CheckForm.tsx

391 lines
15 KiB
TypeScript
Raw Normal View History

2025-09-17 09:02:03 +00:00
import React, { useState, useEffect } from 'react'
import { FaCreditCard, FaSave, FaTimes } from 'react-icons/fa'
import { FiCheck, TypeEnum, CheckStatusEnum, FiCurrentAccount } from '../../../types/fi'
import { getCheckStatusText, getTypeText } from '@/utils/erp'
import { mockCurrencies } from '@/mocks/mockCurrencies'
2025-09-15 09:31:47 +00:00
interface CheckFormProps {
2025-09-17 09:02:03 +00:00
check?: FiCheck
currentAccounts: FiCurrentAccount[]
onSave: (check: Omit<FiCheck, 'id' | 'creationTime' | 'lastModificationTime'>) => void
onCancel: () => void
isOpen: boolean
2025-09-15 09:31:47 +00:00
}
const CheckForm: React.FC<CheckFormProps> = ({
check,
currentAccounts,
onSave,
onCancel,
isOpen,
}) => {
const [formData, setFormData] = useState({
2025-09-17 09:02:03 +00:00
checkNumber: '',
bankName: '',
branchName: '',
accountNumber: '',
drawerName: '',
payeeName: '',
currentAccountId: '',
issueDate: new Date().toISOString().split('T')[0],
dueDate: new Date().toISOString().split('T')[0],
2025-09-15 09:31:47 +00:00
amount: 0,
2025-09-17 09:02:03 +00:00
currency: 'TRY',
2025-09-15 09:31:47 +00:00
status: CheckStatusEnum.InHand,
2025-09-17 09:02:03 +00:00
type: TypeEnum.Received,
notes: '',
})
2025-09-15 09:31:47 +00:00
2025-09-17 09:02:03 +00:00
const [errors, setErrors] = useState<Record<string, string>>({})
2025-09-15 09:31:47 +00:00
useEffect(() => {
if (check) {
setFormData({
checkNumber: check.checkNumber,
bankName: check.bankName,
branchName: check.branchName,
accountNumber: check.accountNumber,
drawerName: check.drawerName,
payeeName: check.payeeName,
2025-09-17 09:02:03 +00:00
currentAccountId: check.currentAccountId || '',
issueDate: new Date(check.issueDate).toISOString().split('T')[0],
dueDate: new Date(check.dueDate).toISOString().split('T')[0],
2025-09-15 09:31:47 +00:00
amount: check.amount,
currency: check.currency,
status: check.status,
type: check.type,
2025-09-17 09:02:03 +00:00
notes: check.notes || '',
})
2025-09-15 09:31:47 +00:00
} else {
setFormData({
2025-09-17 09:02:03 +00:00
checkNumber: '',
bankName: '',
branchName: '',
accountNumber: '',
drawerName: '',
payeeName: '',
currentAccountId: '',
issueDate: new Date().toISOString().split('T')[0],
dueDate: new Date().toISOString().split('T')[0],
2025-09-15 09:31:47 +00:00
amount: 0,
2025-09-17 09:02:03 +00:00
currency: 'TRY',
2025-09-15 09:31:47 +00:00
status: CheckStatusEnum.InHand,
2025-09-17 09:02:03 +00:00
type: TypeEnum.Received,
notes: '',
})
2025-09-15 09:31:47 +00:00
}
2025-09-17 09:02:03 +00:00
setErrors({})
}, [check, isOpen])
2025-09-15 09:31:47 +00:00
const validateForm = () => {
2025-09-17 09:02:03 +00:00
const newErrors: Record<string, string> = {}
2025-09-15 09:31:47 +00:00
if (!formData.checkNumber.trim()) {
2025-09-17 09:02:03 +00:00
newErrors.checkNumber = 'Çek numarası gereklidir'
2025-09-15 09:31:47 +00:00
}
if (!formData.bankName.trim()) {
2025-09-17 09:02:03 +00:00
newErrors.bankName = 'Banka adı gereklidir'
2025-09-15 09:31:47 +00:00
}
if (!formData.drawerName.trim()) {
2025-09-17 09:02:03 +00:00
newErrors.drawerName = 'Keşideci adı gereklidir'
2025-09-15 09:31:47 +00:00
}
if (!formData.payeeName.trim()) {
2025-09-17 09:02:03 +00:00
newErrors.payeeName = 'Lehtar adı gereklidir'
2025-09-15 09:31:47 +00:00
}
if (formData.amount <= 0) {
2025-09-17 09:02:03 +00:00
newErrors.amount = "Tutar 0'dan büyük olmalıdır"
2025-09-15 09:31:47 +00:00
}
if (new Date(formData.dueDate) < new Date(formData.issueDate)) {
2025-09-17 09:02:03 +00:00
newErrors.dueDate = 'Vade tarihi düzenleme tarihinden sonra olmalıdır'
2025-09-15 09:31:47 +00:00
}
2025-09-17 09:02:03 +00:00
setErrors(newErrors)
return Object.keys(newErrors).length === 0
}
2025-09-15 09:31:47 +00:00
const handleSubmit = (e: React.FormEvent) => {
2025-09-17 09:02:03 +00:00
e.preventDefault()
2025-09-15 09:31:47 +00:00
if (validateForm()) {
const checkData = {
...formData,
issueDate: new Date(formData.issueDate),
dueDate: new Date(formData.dueDate),
currentAccount: formData.currentAccountId
? currentAccounts.find((acc) => acc.id === formData.currentAccountId)
: undefined,
2025-09-17 09:02:03 +00:00
}
onSave(checkData)
2025-09-15 09:31:47 +00:00
}
2025-09-17 09:02:03 +00:00
}
2025-09-15 09:31:47 +00:00
const handleInputChange = (
field: string,
2025-09-17 09:02:03 +00:00
value: string | number | TypeEnum | CheckStatusEnum,
2025-09-15 09:31:47 +00:00
) => {
2025-09-17 09:02:03 +00:00
setFormData((prev) => ({ ...prev, [field]: value }))
2025-09-15 09:31:47 +00:00
if (errors[field]) {
2025-09-17 09:02:03 +00:00
setErrors((prev) => ({ ...prev, [field]: '' }))
2025-09-15 09:31:47 +00:00
}
2025-09-17 09:02:03 +00:00
}
2025-09-15 09:31:47 +00:00
2025-09-17 09:02:03 +00:00
if (!isOpen) return null
2025-09-15 09:31:47 +00:00
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg shadow-xl w-full max-w-3xl max-h-[90vh] overflow-y-auto">
<div className="flex items-center justify-between p-4 border-b">
<div className="flex items-center gap-2.5">
<FaCreditCard className="w-5 h-5 text-blue-600" />
<h2 className="text-lg font-semibold text-gray-900">
2025-09-17 09:02:03 +00:00
{check ? 'Çek Düzenle' : 'Yeni Çek'}
2025-09-15 09:31:47 +00:00
</h2>
</div>
2025-09-17 09:02:03 +00:00
<button onClick={onCancel} className="p-2 hover:bg-gray-100 rounded-md">
2025-09-15 09:31:47 +00:00
<FaTimes className="w-5 h-5 text-gray-500" />
</button>
</div>
<form onSubmit={handleSubmit} className="p-4 space-y-4">
{/* Çek Bilgileri */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-3">
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Çek Numarası *</label>
2025-09-15 09:31:47 +00:00
<input
type="text"
value={formData.checkNumber}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('checkNumber', e.target.value)}
2025-09-15 09:31:47 +00:00
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
2025-09-17 09:02:03 +00:00
errors.checkNumber ? 'border-red-500' : 'border-gray-300'
2025-09-15 09:31:47 +00:00
}`}
placeholder="Çek numarasını giriniz"
/>
{errors.checkNumber && (
2025-09-17 09:02:03 +00:00
<p className="text-red-500 text-xs mt-1">{errors.checkNumber}</p>
2025-09-15 09:31:47 +00:00
)}
</div>
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Tür *</label>
2025-09-15 09:31:47 +00:00
<select
value={formData.type}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('type', e.target.value as TypeEnum)}
2025-09-15 09:31:47 +00:00
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
>
2025-09-17 09:02:03 +00:00
{Object.values(TypeEnum).map((type) => (
<option key={type} value={type}>
{getTypeText(type)}
</option>
))}
2025-09-15 09:31:47 +00:00
</select>
</div>
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Durum</label>
2025-09-15 09:31:47 +00:00
<select
value={formData.status}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('status', e.target.value as CheckStatusEnum)}
2025-09-15 09:31:47 +00:00
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
>
2025-09-17 09:02:03 +00:00
{Object.values(CheckStatusEnum).map((status) => (
<option key={status} value={status}>
{getCheckStatusText(status)}
</option>
))}
2025-09-15 09:31:47 +00:00
</select>
</div>
</div>
{/* Banka Bilgileri */}
<div className="bg-gray-50 p-3 rounded-lg">
2025-09-17 09:02:03 +00:00
<h3 className="text-base font-medium text-gray-900 mb-3">Banka Bilgileri</h3>
2025-09-15 09:31:47 +00:00
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Banka Adı *</label>
2025-09-15 09:31:47 +00:00
<input
type="text"
value={formData.bankName}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('bankName', e.target.value)}
2025-09-15 09:31:47 +00:00
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
2025-09-17 09:02:03 +00:00
errors.bankName ? 'border-red-500' : 'border-gray-300'
2025-09-15 09:31:47 +00:00
}`}
placeholder="Banka adını giriniz"
/>
2025-09-17 09:02:03 +00:00
{errors.bankName && <p className="text-red-500 text-xs mt-1">{errors.bankName}</p>}
2025-09-15 09:31:47 +00:00
</div>
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Şube Adı</label>
2025-09-15 09:31:47 +00:00
<input
type="text"
value={formData.branchName}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('branchName', e.target.value)}
2025-09-15 09:31:47 +00:00
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Şube adını giriniz"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Hesap Numarası
</label>
<input
type="text"
value={formData.accountNumber}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('accountNumber', e.target.value)}
2025-09-15 09:31:47 +00:00
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Hesap numarasını giriniz"
/>
</div>
</div>
</div>
{/* Taraf Bilgileri */}
<div className="bg-gray-50 p-3 rounded-lg">
2025-09-17 09:02:03 +00:00
<h3 className="text-base font-medium text-gray-900 mb-3">Taraf Bilgileri</h3>
2025-09-15 09:31:47 +00:00
<div className="grid grid-cols-1 md:grid-cols-3 gap-3">
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Keşideci *</label>
2025-09-15 09:31:47 +00:00
<input
type="text"
value={formData.drawerName}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('drawerName', e.target.value)}
2025-09-15 09:31:47 +00:00
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
2025-09-17 09:02:03 +00:00
errors.drawerName ? 'border-red-500' : 'border-gray-300'
2025-09-15 09:31:47 +00:00
}`}
placeholder="Keşideci adını giriniz"
/>
{errors.drawerName && (
2025-09-17 09:02:03 +00:00
<p className="text-red-500 text-xs mt-1">{errors.drawerName}</p>
2025-09-15 09:31:47 +00:00
)}
</div>
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Lehtar *</label>
2025-09-15 09:31:47 +00:00
<input
type="text"
value={formData.payeeName}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('payeeName', e.target.value)}
2025-09-15 09:31:47 +00:00
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
2025-09-17 09:02:03 +00:00
errors.payeeName ? 'border-red-500' : 'border-gray-300'
2025-09-15 09:31:47 +00:00
}`}
placeholder="Lehtar adını giriniz"
/>
{errors.payeeName && (
2025-09-17 09:02:03 +00:00
<p className="text-red-500 text-xs mt-1">{errors.payeeName}</p>
2025-09-15 09:31:47 +00:00
)}
</div>
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Cari Hesap</label>
2025-09-15 09:31:47 +00:00
<select
value={formData.currentAccountId}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('currentAccountId', e.target.value)}
2025-09-15 09:31:47 +00:00
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option value="">Cari hesap seçiniz</option>
{currentAccounts.map((account) => (
<option key={account.id} value={account.id}>
{account.accountCode} - {account.businessParty?.name}
</option>
))}
</select>
</div>
</div>
</div>
{/* Tutar ve Tarih Bilgileri */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Tutar *</label>
2025-09-15 09:31:47 +00:00
<input
type="number"
step="0.01"
min="0"
value={formData.amount}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('amount', parseFloat(e.target.value) || 0)}
2025-09-15 09:31:47 +00:00
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
2025-09-17 09:02:03 +00:00
errors.amount ? 'border-red-500' : 'border-gray-300'
2025-09-15 09:31:47 +00:00
}`}
placeholder="0.00"
/>
2025-09-17 09:02:03 +00:00
{errors.amount && <p className="text-red-500 text-xs mt-1">{errors.amount}</p>}
2025-09-15 09:31:47 +00:00
</div>
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Para Birimi</label>
2025-09-15 09:31:47 +00:00
<select
value={formData.currency}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('currency', e.target.value)}
2025-09-15 09:31:47 +00:00
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
>
2025-09-17 09:02:03 +00:00
{mockCurrencies.map((currency) => (
<option key={currency.value} value={currency.value}>
{currency.value} - {currency.label}
</option>
))}
2025-09-15 09:31:47 +00:00
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Düzenleme Tarihi *
</label>
<input
type="date"
value={formData.issueDate}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('issueDate', e.target.value)}
2025-09-15 09:31:47 +00:00
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
</div>
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Vade Tarihi *</label>
2025-09-15 09:31:47 +00:00
<input
type="date"
value={formData.dueDate}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('dueDate', e.target.value)}
2025-09-15 09:31:47 +00:00
className={`w-full px-3 py-1.5 text-sm border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${
2025-09-17 09:02:03 +00:00
errors.dueDate ? 'border-red-500' : 'border-gray-300'
2025-09-15 09:31:47 +00:00
}`}
/>
2025-09-17 09:02:03 +00:00
{errors.dueDate && <p className="text-red-500 text-xs mt-1">{errors.dueDate}</p>}
2025-09-15 09:31:47 +00:00
</div>
</div>
{/* Notlar */}
<div>
2025-09-17 09:02:03 +00:00
<label className="block text-sm font-medium text-gray-700 mb-1">Notlar</label>
2025-09-15 09:31:47 +00:00
<textarea
value={formData.notes}
2025-09-17 09:02:03 +00:00
onChange={(e) => handleInputChange('notes', e.target.value)}
2025-09-15 09:31:47 +00:00
rows={3}
className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Ek notlar..."
/>
</div>
{/* Butonlar */}
<div className="flex justify-end gap-3 pt-4 border-t">
<button
type="button"
onClick={onCancel}
className="px-4 py-1.5 text-sm border border-gray-300 text-gray-700 rounded-md hover:bg-gray-50 transition-colors"
>
İptal
</button>
<button
type="submit"
className="flex items-center gap-2 px-4 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors"
>
<FaSave className="w-4 h-4" />
2025-09-17 09:02:03 +00:00
{check ? 'Güncelle' : 'Kaydet'}
2025-09-15 09:31:47 +00:00
</button>
</div>
</form>
</div>
</div>
2025-09-17 09:02:03 +00:00
)
}
2025-09-15 09:31:47 +00:00
2025-09-17 09:02:03 +00:00
export default CheckForm