"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 (
e.target === e.currentTarget && onClose()} >
{/* Header */}

{task?.task_name}

{t(`tasks.${task?.priority}`)} {t(`taskStatus.${task?.status}`)}

{t("tasks.project")}: {task?.project_name}

{/* Task Details Grid */}
{/* Location Information */} {(task?.city || task?.address) && (

{t("projects.locationDetails")}

{task?.city && (

{task.city}

)} {task?.address && (

{task.address}

)}
)} {/* Assignment Information */}

{t("tasks.assignedTo")}

{task?.assigned_to_name ? (

{task.assigned_to_name}

{task.assigned_to_email}

) : (

{t("projects.unassigned")}

)}
{/* Task Timing */}

{t("tasks.dateCreated")}

{task?.max_wait_days && (

{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}

); } else if (task?.status === "in_progress" && task?.date_started) { const dateInfo = formatTaskDate(task.date_started, t("tasks.dateStarted")); return (

{t("tasks.dateStarted")} {dateInfo.relative}

{dateInfo.absolute}

); } else if (task?.date_added) { const dateInfo = formatTaskDate(task.date_added, t("tasks.dateCreated")); return (

{t("tasks.dateCreated")} {dateInfo.relative}

{dateInfo.absolute}

); } return null; })()}
{/* Task Description */} {task?.description && (

{t("tasks.description")}

{task.description}

)}
{/* Content */}
{loading ? (
) : (
{t("tasks.comments")}
{notes.length}
{notes.length === 0 ? (
💬

{t("tasks.noComments")}

Bądź pierwszy, który doda komentarz!

) : (
{notes.map((note) => (
{note.is_system ? ( 🤖 {t("admin.system")} ) : ( 👤 {note.created_by_name || t("userRoles.user")} )} {formatDate(note.note_date, { includeTime: true, })}

{note.note}

{!note.is_system && ( )}
))}
)}
)}
{/* Footer - Add new comment */}
💬