tududi/app/frontend/components/Area/AreaModal.tsx
Chris Veleris dfcb97a355 Move to React
Add .gitignore

Removed node_modules from previous commit

Fix task modes

Fix task modes

Fix task modes

Remove node_modules

Update basic task modal

Add notes functionality

Improve UI

Setup views

Add scopes

Fix projects layout

Restructure

Fix rest of the UI issues

Cleanup old views

Add .env to .gitignore
2024-10-25 21:03:43 +03:00

175 lines
5.9 KiB
TypeScript

import React, { useState, useEffect, useRef } from 'react';
import { Area } from '../../entities/Area';
import { useDataContext } from '../../contexts/DataContext'; // Import DataContext
interface AreaModalProps {
isOpen: boolean;
onClose: () => void;
area?: Area | null;
}
const AreaModal: React.FC<AreaModalProps> = ({ isOpen, onClose, area }) => {
const { createArea, updateArea } = useDataContext(); // Use create and update methods from DataContext
const [formData, setFormData] = useState<Area>({
id: area?.id || 0,
name: area?.name || '',
description: area?.description || '',
});
const [error, setError] = useState<string | null>(null);
const modalRef = useRef<HTMLDivElement>(null);
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
// Synchronize formData with the area prop when the modal opens or area changes
useEffect(() => {
if (isOpen) {
setFormData({
id: area?.id || 0,
name: area?.name || '',
description: area?.description || '',
});
setError(null); // Reset error when modal opens
}
}, [isOpen, area]);
// Close modal when clicking outside of it
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (modalRef.current && !modalRef.current.contains(event.target as Node)) {
onClose();
}
};
if (isOpen) {
document.addEventListener('mousedown', handleClickOutside);
}
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [isOpen, onClose]);
// Handle input changes
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
};
// Handle form submission
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
// Basic validation
if (!formData.name.trim()) {
setError('Area name is required.');
return;
}
setIsSubmitting(true);
setError(null);
try {
if (formData.id && formData.id !== 0) {
await updateArea(formData.id, formData); // Call updateArea from DataContext
} else {
await createArea(formData); // Call createArea from DataContext
}
onClose(); // Close modal after success
} catch (err) {
setError((err as Error).message);
} finally {
setIsSubmitting(false);
}
};
if (!isOpen) return null;
return (
<div className="fixed inset-0 flex items-center justify-center bg-gray-900 bg-opacity-50 z-50">
<div
ref={modalRef}
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
className="bg-white dark:bg-gray-800 rounded-lg shadow-lg w-full max-w-md mx-auto overflow-hidden"
>
<form onSubmit={handleSubmit}>
<fieldset>
<div className="p-4 space-y-4">
<h3 id="modal-title" className="text-lg font-medium text-gray-900 dark:text-white">
{formData.id && formData.id !== 0 ? 'Edit Area' : 'Create Area'}
</h3>
{/* Area Name */}
<div>
<label
htmlFor="areaName"
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
>
Area Name
</label>
<input
type="text"
id="areaName"
name="name"
value={formData.name}
onChange={handleChange}
required
className="mt-1 block w-full border border-gray-300 dark:border-gray-700 rounded-md shadow-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-gray-100"
placeholder="Enter area name"
/>
</div>
{/* Area Description */}
<div>
<label
htmlFor="areaDescription"
className="block text-sm font-medium text-gray-700 dark:text-gray-300"
>
Description
</label>
<textarea
id="areaDescription"
name="description"
value={formData.description}
onChange={handleChange}
rows={3}
className="mt-1 block w-full border border-gray-300 dark:border-gray-700 rounded-md shadow-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-gray-100"
placeholder="Enter area description"
/>
</div>
{/* Error Message */}
{error && <div className="text-red-500">{error}</div>}
</div>
{/* Modal Actions */}
<div className="flex justify-end items-center p-4 border-t border-gray-200 dark:border-gray-700">
<button
type="button"
onClick={onClose}
className="px-4 mr-2 text-xs py-2 bg-gray-200 text-gray-700 rounded hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-200 dark:hover:bg-gray-600 focus:outline-none"
>
Cancel
</button>
<button
type="submit"
disabled={isSubmitting}
className={`px-4 text-xs py-2 bg-blue-600 text-white rounded hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 focus:outline-none ${
isSubmitting ? 'opacity-50 cursor-not-allowed' : ''
}`}
>
{isSubmitting ? 'Submitting...' : formData.id && formData.id !== 0 ? 'Update Area' : 'Create Area'}
</button>
</div>
</fieldset>
</form>
</div>
</div>
);
};
export default AreaModal;