"use client"; import React, { useState, useEffect } from "react"; import Button from "./ui/Button"; import Badge from "./ui/Badge"; import { formatDate } from "@/lib/utils"; import { formatDistanceToNow, parseISO } from "date-fns"; import { useTranslation } from "@/lib/i18n"; export default function TaskCommentsModal({ task, isOpen, onClose }) { const { t } = useTranslation(); const [notes, setNotes] = useState([]); const [loading, setLoading] = useState(true); const [newNote, setNewNote] = useState(""); const [loadingAdd, setLoadingAdd] = useState(false); useEffect(() => { if (isOpen && task) { fetchNotes(); } }, [isOpen, task]); const fetchNotes = async () => { if (!task?.id) return; try { setLoading(true); const res = await fetch(`/api/task-notes?task_id=${task.id}`); const data = await res.json(); setNotes(data); } catch (error) { console.error("Failed to fetch notes:", error); } finally { setLoading(false); } }; const handleAddNote = async () => { if (!newNote.trim() || !task?.id) return; try { setLoadingAdd(true); const res = await fetch("/api/task-notes", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ task_id: task.id, note: newNote.trim(), }), }); if (res.ok) { setNewNote(""); await fetchNotes(); // Refresh notes } else { alert("Failed to add note"); } } catch (error) { alert("Error adding note"); } finally { setLoadingAdd(false); } }; const handleDeleteNote = async (noteId) => { if (!confirm("Are you sure you want to delete this note?")) return; try { const res = await fetch("/api/task-notes", { method: "DELETE", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ note_id: noteId }), }); if (res.ok) { await fetchNotes(); // Refresh notes } else { alert("Failed to delete note"); } } catch (error) { alert("Error deleting note"); } }; const handleKeyDown = (e) => { if (e.key === "Escape") { onClose(); } else if (e.key === "Enter" && e.ctrlKey) { handleAddNote(); } }; const getPriorityVariant = (priority) => { switch (priority) { case "urgent": return "urgent"; case "high": return "high"; case "normal": return "normal"; case "low": return "low"; default: return "default"; } }; const getStatusVariant = (status) => { switch (status) { case "completed": case "cancelled": return "success"; case "in_progress": return "secondary"; case "pending": return "primary"; default: return "default"; } }; const formatTaskDate = (dateString, label) => { if (!dateString) return null; try { const date = dateString.includes("T") ? parseISO(dateString) : new Date(dateString); return { label, relative: formatDistanceToNow(date, { addSuffix: true }), absolute: formatDate(date, { includeTime: true }) }; } catch (error) { return { label, relative: dateString, absolute: dateString }; } }; if (!isOpen) return null; return (
{t("tasks.project")}: {task?.project_name}
{task.city}
)} {task?.address && ({task.address}
)}{task.assigned_to_name}
{task.assigned_to_email}
{t("projects.unassigned")}
)}{t("tasks.maxWait")}: {task.max_wait_days} {t("tasks.days")}
)} {(() => { if (task?.status === "completed" && task?.date_completed) { const dateInfo = formatTaskDate(task.date_completed, t("taskStatus.completed")); return ({dateInfo.relative}
{dateInfo.absolute}
{t("tasks.dateStarted")} {dateInfo.relative}
{dateInfo.absolute}
{t("tasks.dateCreated")} {dateInfo.relative}
{dateInfo.absolute}
{task.description}
{t("tasks.noComments")}
Bądź pierwszy, który doda komentarz!
{note.note}