feat(i18n): Add Polish translations for task management components and update search placeholder
This commit is contained in:
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user