import React, { useState, useEffect, useRef } from 'react'; import { Area } from '../../entities/Area'; import { useToast } from '../Shared/ToastContext'; import { useTranslation } from 'react-i18next'; import { TrashIcon } from '@heroicons/react/24/outline'; interface AreaModalProps { isOpen: boolean; onClose: () => void; onSave: (areaData: Partial) => Promise; onDelete?: (areaId: number) => Promise; area?: Area | null; } const AreaModal: React.FC = ({ isOpen, onClose, area, onSave, onDelete, }) => { const { t } = useTranslation(); const [formData, setFormData] = useState({ id: area?.id || 0, name: area?.name || '', description: area?.description || '', }); const [error, setError] = useState(null); const modalRef = useRef(null); const nameInputRef = useRef(null); const [isSubmitting, setIsSubmitting] = useState(false); const [isClosing, setIsClosing] = useState(false); const { showSuccessToast, showErrorToast } = useToast(); useEffect(() => { if (isOpen) { setFormData({ id: area?.id || 0, name: area?.name || '', description: area?.description || '', }); setError(null); // Auto-focus on the name input when modal opens setTimeout(() => { nameInputRef.current?.focus(); }, 100); } }, [isOpen, area]); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( modalRef.current && !modalRef.current.contains(event.target as Node) ) { handleClose(); } }; if (isOpen) { document.addEventListener('mousedown', handleClickOutside); } return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [isOpen]); useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Escape') { handleClose(); } }; if (isOpen) { document.addEventListener('keydown', handleKeyDown); } return () => { document.removeEventListener('keydown', handleKeyDown); }; }, [isOpen]); const handleChange = ( e: React.ChangeEvent ) => { const { name, value } = e.target; setFormData((prev) => ({ ...prev, [name]: value, })); }; const handleSubmit = async (e?: React.FormEvent) => { if (e) { e.preventDefault(); } if (!formData.name.trim()) { setError(t('errors.areaNameRequired')); return; } setIsSubmitting(true); setError(null); try { await onSave(formData); showSuccessToast( formData.id ? t('success.areaUpdated') : t('success.areaCreated') ); handleClose(); } catch (err) { setError((err as Error).message); showErrorToast(t('errors.failedToSaveArea')); } finally { setIsSubmitting(false); } }; const handleClose = () => { setIsClosing(true); setTimeout(() => { onClose(); setIsClosing(false); }, 300); }; const handleDeleteArea = async () => { if (formData.id && formData.id !== 0 && onDelete) { try { await onDelete(formData.id); showSuccessToast( t('success.areaDeleted', 'Area deleted successfully!') ); handleClose(); } catch (err) { setError((err as Error).message); showErrorToast( t('errors.failedToDeleteArea', 'Failed to delete area.') ); } } }; if (!isOpen) return null; return (
{/* Main Form Section */}
{/* Area Title Section - Always Visible */}
{/* Description Section - Always Visible */}