feat(i18n): Add Polish translations for task management components and update search placeholder
This commit is contained in:
@@ -5,8 +5,10 @@ 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("");
|
||||
@@ -148,14 +150,14 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
{task?.task_name}
|
||||
</h3>
|
||||
<Badge variant={getPriorityVariant(task?.priority)} size="sm">
|
||||
{task?.priority}
|
||||
{t(`tasks.${task?.priority}`)}
|
||||
</Badge>
|
||||
<Badge variant={getStatusVariant(task?.status)} size="sm">
|
||||
{task?.status?.replace('_', ' ')}
|
||||
{t(`taskStatus.${task?.status}`)}
|
||||
</Badge>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 mb-3">
|
||||
Project: <span className="font-medium">{task?.project_name}</span>
|
||||
{t("tasks.project")}: <span className="font-medium">{task?.project_name}</span>
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
@@ -172,7 +174,7 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
{/* Location Information */}
|
||||
{(task?.city || task?.address) && (
|
||||
<div className="space-y-1">
|
||||
<h4 className="text-xs font-medium text-gray-500 uppercase tracking-wide">Location</h4>
|
||||
<h4 className="text-xs font-medium text-gray-500 uppercase tracking-wide">{t("projects.locationDetails")}</h4>
|
||||
{task?.city && (
|
||||
<p className="text-sm text-gray-900">{task.city}</p>
|
||||
)}
|
||||
@@ -184,26 +186,26 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
|
||||
{/* Assignment Information */}
|
||||
<div className="space-y-1">
|
||||
<h4 className="text-xs font-medium text-gray-500 uppercase tracking-wide">Assignment</h4>
|
||||
<h4 className="text-xs font-medium text-gray-500 uppercase tracking-wide">{t("tasks.assignedTo")}</h4>
|
||||
{task?.assigned_to_name ? (
|
||||
<div>
|
||||
<p className="text-sm text-gray-900">{task.assigned_to_name}</p>
|
||||
<p className="text-xs text-gray-600">{task.assigned_to_email}</p>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-gray-500 italic">Unassigned</p>
|
||||
<p className="text-sm text-gray-500 italic">{t("projects.unassigned")}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Task Timing */}
|
||||
<div className="space-y-1">
|
||||
<h4 className="text-xs font-medium text-gray-500 uppercase tracking-wide">Timing</h4>
|
||||
<h4 className="text-xs font-medium text-gray-500 uppercase tracking-wide">{t("tasks.dateCreated")}</h4>
|
||||
{task?.max_wait_days && (
|
||||
<p className="text-xs text-gray-600">Max wait: {task.max_wait_days} days</p>
|
||||
<p className="text-xs text-gray-600">{t("tasks.maxWait")}: {task.max_wait_days} {t("tasks.days")}</p>
|
||||
)}
|
||||
{(() => {
|
||||
if (task?.status === "completed" && task?.date_completed) {
|
||||
const dateInfo = formatTaskDate(task.date_completed, "Completed");
|
||||
const dateInfo = formatTaskDate(task.date_completed, t("taskStatus.completed"));
|
||||
return (
|
||||
<div>
|
||||
<p className="text-sm text-green-700 font-medium">{dateInfo.relative}</p>
|
||||
@@ -211,18 +213,18 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
</div>
|
||||
);
|
||||
} else if (task?.status === "in_progress" && task?.date_started) {
|
||||
const dateInfo = formatTaskDate(task.date_started, "Started");
|
||||
const dateInfo = formatTaskDate(task.date_started, t("tasks.dateStarted"));
|
||||
return (
|
||||
<div>
|
||||
<p className="text-sm text-blue-700 font-medium">Started {dateInfo.relative}</p>
|
||||
<p className="text-sm text-blue-700 font-medium">{t("tasks.dateStarted")} {dateInfo.relative}</p>
|
||||
<p className="text-xs text-gray-600">{dateInfo.absolute}</p>
|
||||
</div>
|
||||
);
|
||||
} else if (task?.date_added) {
|
||||
const dateInfo = formatTaskDate(task.date_added, "Created");
|
||||
const dateInfo = formatTaskDate(task.date_added, t("tasks.dateCreated"));
|
||||
return (
|
||||
<div>
|
||||
<p className="text-sm text-gray-700 font-medium">Created {dateInfo.relative}</p>
|
||||
<p className="text-sm text-gray-700 font-medium">{t("tasks.dateCreated")} {dateInfo.relative}</p>
|
||||
<p className="text-xs text-gray-600">{dateInfo.absolute}</p>
|
||||
</div>
|
||||
);
|
||||
@@ -234,7 +236,7 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
{/* Task Description */}
|
||||
{task?.description && (
|
||||
<div className="space-y-1 md:col-span-2 lg:col-span-3">
|
||||
<h4 className="text-xs font-medium text-gray-500 uppercase tracking-wide">Description</h4>
|
||||
<h4 className="text-xs font-medium text-gray-500 uppercase tracking-wide">{t("tasks.description")}</h4>
|
||||
<p className="text-sm text-gray-900 leading-relaxed">{task.description}</p>
|
||||
</div>
|
||||
)}
|
||||
@@ -255,7 +257,7 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<h5 className="text-lg font-medium text-gray-900">
|
||||
Comments & Activity
|
||||
{t("tasks.comments")}
|
||||
</h5>
|
||||
<Badge variant="secondary" size="sm">
|
||||
{notes.length}
|
||||
@@ -267,8 +269,8 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
<div className="w-16 h-16 mx-auto mb-4 bg-gray-100 rounded-full flex items-center justify-center">
|
||||
<span className="text-2xl">💬</span>
|
||||
</div>
|
||||
<p className="text-lg font-medium mb-1">No comments yet</p>
|
||||
<p className="text-sm">Be the first to add a comment!</p>
|
||||
<p className="text-lg font-medium mb-1">{t("tasks.noComments")}</p>
|
||||
<p className="text-sm">Bądź pierwszy, który doda komentarz!</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
@@ -286,12 +288,12 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
{note.is_system ? (
|
||||
<span className="px-2 py-1 text-xs bg-blue-100 text-blue-700 rounded-full font-medium flex items-center gap-1">
|
||||
<span>🤖</span>
|
||||
System
|
||||
{t("admin.system")}
|
||||
</span>
|
||||
) : (
|
||||
<span className="px-2 py-1 text-xs bg-gray-100 text-gray-700 rounded-full font-medium flex items-center gap-1">
|
||||
<span>👤</span>
|
||||
{note.created_by_name || 'User'}
|
||||
{note.created_by_name || t("userRoles.user")}
|
||||
</span>
|
||||
)}
|
||||
<span className="text-xs text-gray-500 font-medium">
|
||||
@@ -308,7 +310,7 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
<button
|
||||
onClick={() => handleDeleteNote(note.note_id)}
|
||||
className="ml-3 p-1 text-red-400 hover:text-red-600 hover:bg-red-50 rounded transition-colors"
|
||||
title="Delete comment"
|
||||
title={t("common.delete")}
|
||||
>
|
||||
<span className="text-sm">🗑️</span>
|
||||
</button>
|
||||
@@ -327,13 +329,13 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-lg">💬</span>
|
||||
<label className="text-sm font-medium text-gray-700">
|
||||
Add a comment
|
||||
{t("tasks.addComment")}
|
||||
</label>
|
||||
</div>
|
||||
<textarea
|
||||
value={newNote}
|
||||
onChange={(e) => setNewNote(e.target.value)}
|
||||
placeholder="Type your comment here... (Ctrl+Enter to submit)"
|
||||
placeholder={t("common.addNotePlaceholder")}
|
||||
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none shadow-sm"
|
||||
rows={3}
|
||||
onKeyDown={handleKeyDown}
|
||||
@@ -341,7 +343,7 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-xs text-gray-500 flex items-center gap-1">
|
||||
<span>⌨️</span>
|
||||
Press Ctrl+Enter to submit or Escape to close
|
||||
Naciśnij Ctrl+Enter aby wysłać lub Escape aby zamknąć
|
||||
</p>
|
||||
<div className="flex gap-3">
|
||||
<Button
|
||||
@@ -349,7 +351,7 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
size="sm"
|
||||
onClick={onClose}
|
||||
>
|
||||
Close
|
||||
{t("common.close")}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
@@ -357,7 +359,7 @@ export default function TaskCommentsModal({ task, isOpen, onClose }) {
|
||||
onClick={handleAddNote}
|
||||
disabled={loadingAdd || !newNote.trim()}
|
||||
>
|
||||
{loadingAdd ? "Adding..." : "💾 Add Comment"}
|
||||
{loadingAdd ? t("common.saving") : `💾 ${t("tasks.addComment")}`}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user