feat(i18n): Add Polish translations for task management components and update search placeholder

This commit is contained in:
Chop
2025-07-27 23:54:56 +02:00
parent e828aa660b
commit 747a68832e
4 changed files with 74 additions and 72 deletions

View File

@@ -15,8 +15,10 @@ import {
formatDistanceToNow,
} from "date-fns";
import { formatDate } from "@/lib/utils";
import { useTranslation } from "@/lib/i18n";
export default function ProjectTasksList() {
const { t } = useTranslation();
const [allTasks, setAllTasks] = useState([]);
const [loading, setLoading] = useState(true);
const [searchTerm, setSearchTerm] = useState("");
@@ -210,7 +212,7 @@ export default function ProjectTasksList() {
// Group tasks by task name when groupBy is set to "task_name"
const groupTasksByName = (tasks) => {
if (groupBy !== "task_name") return { "All Tasks": tasks };
if (groupBy !== "task_name") return { [t("tasks.allTasks")]: tasks };
const groups = {};
tasks.forEach((task) => {
@@ -238,10 +240,10 @@ export default function ProjectTasksList() {
const tasks = await res2.json();
setAllTasks(tasks);
} else {
alert("Failed to update task status");
alert(t("errors.generic"));
}
} catch (error) {
alert("Error updating task status");
alert(t("errors.generic"));
}
};
@@ -281,7 +283,7 @@ export default function ProjectTasksList() {
<div className="flex items-center gap-2">
<span className="font-medium text-gray-900">{task.task_name}</span>
<Badge variant={getPriorityVariant(task.priority)} size="sm">
{task.priority}
{t(`tasks.${task.priority}`)}
</Badge>
</div>
</td>
@@ -307,7 +309,7 @@ export default function ProjectTasksList() {
</div>
</div>
) : (
<span className="text-gray-400 italic">Unassigned</span>
<span className="text-gray-400 italic">{t("projects.unassigned")}</span>
)}
</td>
{showTimeLeft && (
@@ -322,9 +324,9 @@ export default function ProjectTasksList() {
>
{!isNaN(task.statusInfo.daysRemaining)
? task.statusInfo.daysRemaining > 0
? `${task.statusInfo.daysRemaining}d left`
: `${Math.abs(task.statusInfo.daysRemaining)}d overdue`
: "Calculating..."}
? `${task.statusInfo.daysRemaining}${t("tasks.daysLeft")}`
: `${Math.abs(task.statusInfo.daysRemaining)}${t("tasks.daysOverdue")}`
: t("common.loading")}
</Badge>
)}
{task.statusInfo &&
@@ -332,8 +334,8 @@ export default function ProjectTasksList() {
task.status === "in_progress" && (
<Badge variant="danger" size="sm">
{!isNaN(task.statusInfo.daysRemaining)
? `${Math.abs(task.statusInfo.daysRemaining)}d overdue`
: "Overdue"}
? `${Math.abs(task.statusInfo.daysRemaining)}${t("tasks.daysOverdue")}`
: t("tasks.overdue")}
</Badge>
)}
</div>
@@ -343,7 +345,7 @@ export default function ProjectTasksList() {
{task.status === "completed" && task.date_completed ? (
<div>
<div>
Completed:{" "}
{t("taskStatus.completed")}:{" "}
{(() => {
try {
const completedDate = new Date(task.date_completed);
@@ -359,7 +361,7 @@ export default function ProjectTasksList() {
) : task.status === "in_progress" && task.date_started ? (
<div>
<div>
Started:{" "}
{t("tasks.dateStarted")}:{" "}
{(() => {
try {
const startedDate = new Date(task.date_started);
@@ -385,7 +387,7 @@ export default function ProjectTasksList() {
</td>
{showMaxWait && (
<td className="px-4 py-3 text-sm text-gray-500">
{task.max_wait_days} days
{task.max_wait_days} {t("tasks.days")}
</td>
)}
<td className="px-4 py-3">
@@ -399,7 +401,7 @@ export default function ProjectTasksList() {
variant="secondary"
size="sm"
onClick={() => handleShowComments(task)}
title="View comments"
title={t("tasks.comments")}
>
💬
</Button>
@@ -418,48 +420,48 @@ export default function ProjectTasksList() {
<thead className="bg-gray-50">
<tr>
<th className="px-4 py-3 text-left text-sm font-medium text-gray-700">
Task Name
{t("tasks.taskName")}
</th>{" "}
<th className="px-4 py-3 text-left text-sm font-medium text-gray-700">
Project
{t("tasks.project")}
</th>
<th className="px-4 py-3 text-left text-sm font-medium text-gray-700">
City
{t("projects.city")}
</th>
<th className="px-4 py-3 text-left text-sm font-medium text-gray-700">
Address
{t("projects.address")}
</th>
<th className="px-4 py-3 text-left text-sm font-medium text-gray-700">
Assigned To
{t("tasks.assignedTo")}
</th>
{showTimeLeft && (
<th className="px-4 py-3 text-left text-sm font-medium text-gray-700">
Time Left
{t("tasks.daysLeft")}
</th>
)}
<th className="px-4 py-3 text-left text-sm font-medium text-gray-700">
Date Info
{t("tasks.dateCreated")}
</th>
{showMaxWait && (
<th className="px-4 py-3 text-left text-sm font-medium text-gray-700">
Max Wait
{t("tasks.maxWait")}
</th>
)}{" "}
<th className="px-4 py-3 text-left text-sm font-medium text-gray-700">
Actions
{t("tasks.actions")}
</th>
</tr>
</thead>
<tbody>
{Object.entries(groupedTasks).map(([groupName, groupTasks]) => (
<Fragment key={`group-fragment-${groupName}`}>
{showGrouped && groupName !== "All Tasks" && (
{showGrouped && groupName !== t("tasks.allTasks") && (
<tr key={`group-${groupName}`}>
<td
colSpan={colSpan}
className="px-4 py-2 bg-gray-100 font-medium text-gray-800 text-sm"
>
{groupName} ({groupTasks.length} tasks)
{groupName} ({groupTasks.length} {t("tasks.tasks")})
</td>
</tr>
)}
@@ -477,7 +479,7 @@ export default function ProjectTasksList() {
</table>
{filteredTasks.length === 0 && (
<div className="text-center py-8 text-gray-500">
<p>No tasks found</p>
<p>{t("tasks.noTasks")}</p>
</div>
)}
</div>
@@ -503,7 +505,7 @@ export default function ProjectTasksList() {
<div className="text-2xl font-bold text-blue-600">
{taskGroups.pending.length}
</div>
<div className="text-sm text-gray-600">Pending</div>
<div className="text-sm text-gray-600">{t("taskStatus.pending")}</div>
</CardContent>
</Card>
<Card>
@@ -511,7 +513,7 @@ export default function ProjectTasksList() {
<div className="text-2xl font-bold text-purple-600">
{taskGroups.in_progress.length}
</div>
<div className="text-sm text-gray-600">In Progress</div>
<div className="text-sm text-gray-600">{t("taskStatus.in_progress")}</div>
</CardContent>
</Card>
<Card>
@@ -519,7 +521,7 @@ export default function ProjectTasksList() {
<div className="text-2xl font-bold text-green-600">
{taskGroups.completed.length}
</div>
<div className="text-sm text-gray-600">Completed</div>
<div className="text-sm text-gray-600">{t("taskStatus.completed")}</div>
</CardContent>
</Card>
</div>{" "}
@@ -527,26 +529,26 @@ export default function ProjectTasksList() {
<SearchBar
searchTerm={searchTerm}
onSearchChange={(e) => setSearchTerm(e.target.value)}
placeholder="Search tasks, projects, city, or address..."
placeholder={t("tasks.searchPlaceholder")}
resultsCount={
filterTasks(taskGroups.pending).length +
filterTasks(taskGroups.in_progress).length +
filterTasks(taskGroups.completed).length
}
resultsText="tasks"
resultsText={t("tasks.tasks")}
filters={
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<label className="text-sm font-medium text-gray-700">
Group by:
{t("tasks.sortBy")}:
</label>
<Select
value={groupBy}
onChange={(e) => setGroupBy(e.target.value)}
className="min-w-[120px]"
>
<option value="none">None</option>
<option value="task_name">Task Name</option>
<option value="none">{t("common.none")}</option>
<option value="task_name">{t("tasks.taskName")}</option>
</Select>
</div>
</div>
@@ -558,13 +560,13 @@ export default function ProjectTasksList() {
<div>
<div className="mb-4">
<h2 className="text-xl font-semibold text-gray-900 flex items-center gap-2">
Pending Tasks
{t("taskStatus.pending")} {t("tasks.tasks")}
<Badge variant="primary" size="md">
{taskGroups.pending.length}
</Badge>
</h2>
<p className="text-sm text-gray-600 mt-1">
Tasks waiting to be started
{t("tasks.noTasksMessage")}
</p>
</div>
<TaskTable
@@ -579,13 +581,13 @@ export default function ProjectTasksList() {
<div>
<div className="mb-4">
<h2 className="text-xl font-semibold text-gray-900 flex items-center gap-2">
In Progress Tasks
{t("taskStatus.in_progress")} {t("tasks.tasks")}
<Badge variant="secondary" size="md">
{taskGroups.in_progress.length}
</Badge>
</h2>
<p className="text-sm text-gray-600 mt-1">
Tasks currently being worked on - showing time left for completion
Zadania aktualnie w trakcie realizacji - pokazujący pozostały czas do ukończenia
</p>
</div>
<TaskTable
@@ -600,13 +602,13 @@ export default function ProjectTasksList() {
<div>
<div className="mb-4">
<h2 className="text-xl font-semibold text-gray-900 flex items-center gap-2">
Completed Tasks
{t("taskStatus.completed")} {t("tasks.tasks")}
<Badge variant="success" size="md">
{taskGroups.completed.length}
</Badge>
</h2>
<p className="text-sm text-gray-600 mt-1">
Recently completed and cancelled tasks
Ostatnio ukończone i anulowane zadania
</p>
</div>
<TaskTable
@@ -616,9 +618,7 @@ export default function ProjectTasksList() {
showMaxWait={false}
/>
</div>
</div>
{/* Comments Modal */}
</div> {/* Comments Modal */}
<TaskCommentsModal
task={selectedTask}
isOpen={showCommentsModal}