import React, { useState, useEffect, useRef, useCallback } from "react"; import { Area } from "../../entities/Area"; import { Project } from "../../entities/Project"; import ConfirmDialog from "../Shared/ConfirmDialog"; import { useToast } from "../Shared/ToastContext"; import TagInput from "../Tag/TagInput"; import PriorityDropdown from "../Shared/PriorityDropdown"; import { PriorityType } from "../../entities/Task"; import Switch from "../Shared/Switch"; import { useStore } from "../../store/useStore"; import { fetchTags } from "../../utils/tagsService"; import { useTranslation } from "react-i18next"; interface ProjectModalProps { isOpen: boolean; onClose: () => void; onSave: (project: Project) => void; onDelete?: (projectId: number) => void; project?: Project; areas: Area[]; } const ProjectModal: React.FC = ({ isOpen, onClose, onSave, onDelete, project, areas, }) => { const [formData, setFormData] = useState( project || { name: "", description: "", area_id: null, active: true, tags: [], priority: "low", due_date_at: "", } ); const [tags, setTags] = useState( project?.tags?.map((tag) => tag.name) || [] ); const { tagsStore } = useStore(); const { tags: availableTags } = tagsStore; const modalRef = useRef(null); const [isClosing, setIsClosing] = useState(false); const [showConfirmDialog, setShowConfirmDialog] = useState(false); const { showSuccessToast } = useToast(); const { t } = useTranslation(); useEffect(() => { if (project) { setFormData({ ...project, tags: project.tags || [], due_date_at: project.due_date_at || "", }); setTags(project.tags?.map((tag) => tag.name) || []); } else { setFormData({ name: "", description: "", area_id: null, active: true, tags: [], priority: "low", due_date_at: "", }); setTags([]); } }, [project]); useEffect(() => { if (availableTags.length === 0) { fetchTags(); } }, [availableTags.length]); 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< HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement > ) => { const target = e.target; const { name, type, value } = target; if (type === "checkbox") { if (target instanceof HTMLInputElement) { const checked = target.checked; setFormData((prev) => ({ ...prev, [name]: checked, })); } } else { setFormData((prev) => ({ ...prev, [name]: value, })); } }; const handleTagsChange = useCallback((newTags: string[]) => { setTags(newTags); setFormData((prev) => ({ ...prev, tags: newTags.map((name) => ({ name })), })); }, []); const handleSubmit = () => { onSave({ ...formData, tags: tags.map((name) => ({ name })) }); showSuccessToast( project ? "Project updated successfully!" : "Project created successfully!" ); handleClose(); }; const handleDeleteClick = () => { setShowConfirmDialog(true); }; const handleDeleteConfirm = () => { if (project && project.id && onDelete) { onDelete(project.id); showSuccessToast("Project deleted successfully!"); setShowConfirmDialog(false); handleClose(); } }; const handleClose = () => { setIsClosing(true); setTimeout(() => { onClose(); setIsClosing(false); }, 300); }; const handleToggleActive = () => { setFormData((prev) => ({ ...prev, active: !prev.active, })); }; if (!isOpen) return null; return ( <>
setFormData({ ...formData, priority: value }) } />
{project && onDelete && ( )}
{showConfirmDialog && ( setShowConfirmDialog(false)} /> )} ); }; export default ProjectModal;