244 lines
9.2 KiB
TypeScript
244 lines
9.2 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
||
import { Chemical } from '../types';
|
||
import { X } from 'lucide-react';
|
||
|
||
interface ChemicalFormProps {
|
||
chemical?: Chemical | null;
|
||
onSave: (chemical: Omit<Chemical, 'id' | 'createdAt' | 'updatedAt'>) => void;
|
||
onCancel: () => void;
|
||
}
|
||
|
||
const ChemicalForm: React.FC<ChemicalFormProps> = ({ chemical, onSave, onCancel }) => {
|
||
const [formData, setFormData] = useState({
|
||
name: '',
|
||
brand: '',
|
||
type: 'pesticide' as Chemical['type'],
|
||
activeIngredient: '',
|
||
concentration: '',
|
||
targetPests: '',
|
||
applicationMethod: '',
|
||
safetyPeriod: '',
|
||
notes: ''
|
||
});
|
||
|
||
useEffect(() => {
|
||
if (chemical) {
|
||
setFormData({
|
||
name: chemical.name,
|
||
brand: chemical.brand || '',
|
||
type: chemical.type,
|
||
activeIngredient: chemical.activeIngredient || '',
|
||
concentration: chemical.concentration || '',
|
||
targetPests: chemical.targetPests || '',
|
||
applicationMethod: chemical.applicationMethod || '',
|
||
safetyPeriod: chemical.safetyPeriod?.toString() || '',
|
||
notes: chemical.notes || ''
|
||
});
|
||
}
|
||
}, [chemical]);
|
||
|
||
const handleSubmit = (e: React.FormEvent) => {
|
||
e.preventDefault();
|
||
onSave({
|
||
...formData,
|
||
brand: formData.brand || undefined,
|
||
activeIngredient: formData.activeIngredient || undefined,
|
||
concentration: formData.concentration || undefined,
|
||
targetPests: formData.targetPests || undefined,
|
||
applicationMethod: formData.applicationMethod || undefined,
|
||
safetyPeriod: formData.safetyPeriod ? parseInt(formData.safetyPeriod) : undefined,
|
||
notes: formData.notes || undefined
|
||
});
|
||
};
|
||
|
||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>) => {
|
||
const { name, value } = e.target;
|
||
setFormData(prev => ({ ...prev, [name]: value }));
|
||
};
|
||
|
||
return (
|
||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
|
||
<div className="bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[90vh] overflow-y-auto">
|
||
<div className="flex justify-between items-center p-6 border-b border-gray-200">
|
||
<h3 className="text-lg font-semibold text-gray-900">
|
||
{chemical ? 'Сохранить' : 'Добавить'}
|
||
</h3>
|
||
<button
|
||
onClick={onCancel}
|
||
className="text-gray-400 hover:text-gray-600 transition-colors"
|
||
>
|
||
<X className="h-5 w-5" />
|
||
</button>
|
||
</div>
|
||
|
||
<form onSubmit={handleSubmit} className="p-6 space-y-4">
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
<div>
|
||
<label htmlFor="name" className="block text-sm font-medium text-gray-700 mb-1">
|
||
Наименование *
|
||
</label>
|
||
<input
|
||
type="text"
|
||
id="name"
|
||
name="name"
|
||
value={formData.name}
|
||
onChange={handleChange}
|
||
placeholder="e.g., Neem Oil"
|
||
required
|
||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<label htmlFor="brand" className="block text-sm font-medium text-gray-700 mb-1">
|
||
Марка
|
||
</label>
|
||
<input
|
||
type="text"
|
||
id="brand"
|
||
name="brand"
|
||
value={formData.brand}
|
||
onChange={handleChange}
|
||
placeholder="e.g., Garden Safe"
|
||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
<div>
|
||
<label htmlFor="type" className="block text-sm font-medium text-gray-700 mb-1">
|
||
Тип *
|
||
</label>
|
||
<select
|
||
id="type"
|
||
name="type"
|
||
value={formData.type}
|
||
onChange={handleChange}
|
||
required
|
||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
|
||
>
|
||
<option value="pesticide">Pesticide</option>
|
||
<option value="herbicide">Herbicide</option>
|
||
<option value="fungicide">Fungicide</option>
|
||
<option value="insecticide">Insecticide</option>
|
||
<option value="miticide">Miticide</option>
|
||
</select>
|
||
</div>
|
||
|
||
<div>
|
||
<label htmlFor="concentration" className="block text-sm font-medium text-gray-700 mb-1">
|
||
Концентрация
|
||
</label>
|
||
<input
|
||
type="text"
|
||
id="concentration"
|
||
name="concentration"
|
||
value={formData.concentration}
|
||
onChange={handleChange}
|
||
placeholder="e.g., 0.9%"
|
||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<label htmlFor="activeIngredient" className="block text-sm font-medium text-gray-700 mb-1">
|
||
Активные ингредиенты
|
||
</label>
|
||
<input
|
||
type="text"
|
||
id="activeIngredient"
|
||
name="activeIngredient"
|
||
value={formData.activeIngredient}
|
||
onChange={handleChange}
|
||
placeholder="e.g., Azadirachtin"
|
||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<label htmlFor="targetPests" className="block text-sm font-medium text-gray-700 mb-1">
|
||
Потив вредителей
|
||
</label>
|
||
<textarea
|
||
id="targetPests"
|
||
name="targetPests"
|
||
value={formData.targetPests}
|
||
onChange={handleChange}
|
||
placeholder="e.g., Aphids, whiteflies, spider mites"
|
||
rows={2}
|
||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent resize-none"
|
||
/>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||
<div>
|
||
<label htmlFor="applicationMethod" className="block text-sm font-medium text-gray-700 mb-1">
|
||
Способ нанесения
|
||
</label>
|
||
<input
|
||
type="text"
|
||
id="applicationMethod"
|
||
name="applicationMethod"
|
||
value={formData.applicationMethod}
|
||
onChange={handleChange}
|
||
placeholder="e.g., Foliar spray"
|
||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<label htmlFor="safetyPeriod" className="block text-sm font-medium text-gray-700 mb-1">
|
||
Безопасный период (дни)
|
||
</label>
|
||
<input
|
||
type="number"
|
||
id="safetyPeriod"
|
||
name="safetyPeriod"
|
||
value={formData.safetyPeriod}
|
||
onChange={handleChange}
|
||
min="0"
|
||
placeholder="e.g., 7"
|
||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<label htmlFor="notes" className="block text-sm font-medium text-gray-700 mb-1">
|
||
Заметки
|
||
</label>
|
||
<textarea
|
||
id="notes"
|
||
name="notes"
|
||
value={formData.notes}
|
||
onChange={handleChange}
|
||
placeholder="Safety instructions, usage notes, etc..."
|
||
rows={3}
|
||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent resize-none"
|
||
/>
|
||
</div>
|
||
|
||
<div className="flex justify-end space-x-3 pt-4 border-t border-gray-200">
|
||
<button
|
||
type="button"
|
||
onClick={onCancel}
|
||
className="px-4 py-2 text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-md transition-colors"
|
||
>
|
||
Отмена
|
||
</button>
|
||
<button
|
||
type="submit"
|
||
className="px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded-md transition-colors"
|
||
>
|
||
{chemical ? 'Сохранить' : 'Добавить'}
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default ChemicalForm; |