Add missing translations for project templates and task details
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
Adds new translation keys for project templates and task details in `en.json` and `de.json`, and updates `ProjectTemplate.tsx` to use these translations. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ceced2fc-aa46-458d-ba87-ddd4b7bb1518 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/659922a9-0087-461c-90dd-6d9a58b81d4d/ceced2fc-aa46-458d-ba87-ddd4b7bb1518/iGgwDyZ
This commit is contained in:
@@ -30,10 +30,6 @@ externalPort = 3000
|
|||||||
localPort = 44261
|
localPort = 44261
|
||||||
externalPort = 3003
|
externalPort = 3003
|
||||||
|
|
||||||
[[ports]]
|
|
||||||
localPort = 46755
|
|
||||||
externalPort = 4200
|
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
PORT = "5000"
|
PORT = "5000"
|
||||||
|
|
||||||
|
|||||||
@@ -677,7 +677,7 @@ export default function ProjectTemplate({
|
|||||||
{/* Closed Projects Section */}
|
{/* Closed Projects Section */}
|
||||||
<div className="space-y-4 mt-8">
|
<div className="space-y-4 mt-8">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h3 className="text-lg font-semibold">Closed Projects</h3>
|
<h3 className="text-lg font-semibold">{t('projectTemplate.closedProjects')}</h3>
|
||||||
<Input
|
<Input
|
||||||
placeholder="Filter closed projects..."
|
placeholder="Filter closed projects..."
|
||||||
value={closedProjectsFilter}
|
value={closedProjectsFilter}
|
||||||
@@ -1124,25 +1124,25 @@ export default function ProjectTemplate({
|
|||||||
{/* Project Details */}
|
{/* Project Details */}
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-sm font-medium">Project Name</label>
|
<label className="text-sm font-medium">{t('projectTemplate.projectName')}</label>
|
||||||
<Input
|
<Input
|
||||||
value={selectedProject.name}
|
value={selectedProject.name}
|
||||||
onChange={(e) => setSelectedProject({ ...selectedProject, name: e.target.value })}
|
onChange={(e) => setSelectedProject({ ...selectedProject, name: e.target.value })}
|
||||||
placeholder="Enter project name"
|
placeholder={t('projectTemplate.projectNamePlaceholder')}
|
||||||
data-testid="input-edit-project-name"
|
data-testid="input-edit-project-name"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-sm font-medium">Description (Optional)</label>
|
<label className="text-sm font-medium">{t('projectTemplate.projectDescription')}</label>
|
||||||
<Input
|
<Input
|
||||||
value={selectedProject.description || ''}
|
value={selectedProject.description || ''}
|
||||||
onChange={(e) => setSelectedProject({ ...selectedProject, description: e.target.value })}
|
onChange={(e) => setSelectedProject({ ...selectedProject, description: e.target.value })}
|
||||||
placeholder="Enter project description"
|
placeholder={t('projectTemplate.projectDescriptionPlaceholder')}
|
||||||
data-testid="input-edit-project-description"
|
data-testid="input-edit-project-description"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-sm font-medium">Status</label>
|
<label className="text-sm font-medium">{t('projectTemplate.status')}</label>
|
||||||
<Select
|
<Select
|
||||||
value={selectedProject.status}
|
value={selectedProject.status}
|
||||||
onValueChange={(value: Project['status']) =>
|
onValueChange={(value: Project['status']) =>
|
||||||
@@ -1153,9 +1153,9 @@ export default function ProjectTemplate({
|
|||||||
<SelectValue />
|
<SelectValue />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="planning">Planning</SelectItem>
|
<SelectItem value="planning">{t('projectTemplate.planning')}</SelectItem>
|
||||||
<SelectItem value="active">Active</SelectItem>
|
<SelectItem value="active">{t('projectTemplate.active')}</SelectItem>
|
||||||
<SelectItem value="finished">Finished</SelectItem>
|
<SelectItem value="finished">{t('projectTemplate.finished')}</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
@@ -1163,7 +1163,7 @@ export default function ProjectTemplate({
|
|||||||
|
|
||||||
{/* Planned End Date */}
|
{/* Planned End Date */}
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<label className="text-sm font-medium">Planned End Date (Optional)</label>
|
<label className="text-sm font-medium">{t('projectTemplate.plannedEndDate')}</label>
|
||||||
<Popover open={isPlannedEndDateCalendarOpen} onOpenChange={setIsPlannedEndDateCalendarOpen}>
|
<Popover open={isPlannedEndDateCalendarOpen} onOpenChange={setIsPlannedEndDateCalendarOpen}>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
@@ -1174,7 +1174,7 @@ export default function ProjectTemplate({
|
|||||||
<CalendarIcon className="mr-2 h-4 w-4" />
|
<CalendarIcon className="mr-2 h-4 w-4" />
|
||||||
{selectedProject.plannedEndDate
|
{selectedProject.plannedEndDate
|
||||||
? selectedProject.plannedEndDate.toLocaleDateString()
|
? selectedProject.plannedEndDate.toLocaleDateString()
|
||||||
: "Select planned end date"}
|
: t('projectTemplate.selectPlannedEndDate')}
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="w-auto p-0" align="start">
|
<PopoverContent className="w-auto p-0" align="start">
|
||||||
@@ -1198,7 +1198,7 @@ export default function ProjectTemplate({
|
|||||||
className="text-xs text-muted-foreground hover:text-destructive"
|
className="text-xs text-muted-foreground hover:text-destructive"
|
||||||
data-testid="button-clear-planned-end-date"
|
data-testid="button-clear-planned-end-date"
|
||||||
>
|
>
|
||||||
Clear date
|
{t('projectTemplate.clearDate')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -1206,7 +1206,7 @@ export default function ProjectTemplate({
|
|||||||
{/* Tasks Section */}
|
{/* Tasks Section */}
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<h3 className="text-lg font-semibold">Project Tasks</h3>
|
<h3 className="text-lg font-semibold">{t('projectTemplate.projectTasks')}</h3>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -1214,7 +1214,7 @@ export default function ProjectTemplate({
|
|||||||
data-testid="button-add-task-edit"
|
data-testid="button-add-task-edit"
|
||||||
>
|
>
|
||||||
<Plus className="w-4 h-4 mr-2" />
|
<Plus className="w-4 h-4 mr-2" />
|
||||||
Add Task
|
{t('projectTemplate.addTask')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -1227,29 +1227,29 @@ export default function ProjectTemplate({
|
|||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<label className="text-xs font-medium text-muted-foreground">Task Title</label>
|
<label className="text-xs font-medium text-muted-foreground">{t('projectTemplate.taskTitle')}</label>
|
||||||
<Input
|
<Input
|
||||||
value={taskForm.title || ''}
|
value={taskForm.title || ''}
|
||||||
onChange={(e) => setTaskForm({...taskForm, title: e.target.value})}
|
onChange={(e) => setTaskForm({...taskForm, title: e.target.value})}
|
||||||
placeholder="Enter task title"
|
placeholder={t('projectTemplate.enterTaskTitle')}
|
||||||
className="text-sm"
|
className="text-sm"
|
||||||
data-testid={`input-inline-task-title-${index}`}
|
data-testid={`input-inline-task-title-${index}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<label className="text-xs font-medium text-muted-foreground">Description</label>
|
<label className="text-xs font-medium text-muted-foreground">{t('projectTemplate.description')}</label>
|
||||||
<Input
|
<Input
|
||||||
value={taskForm.description || ''}
|
value={taskForm.description || ''}
|
||||||
onChange={(e) => setTaskForm({...taskForm, description: e.target.value})}
|
onChange={(e) => setTaskForm({...taskForm, description: e.target.value})}
|
||||||
placeholder="Enter task description"
|
placeholder={t('projectTemplate.enterTaskDescription')}
|
||||||
className="text-sm"
|
className="text-sm"
|
||||||
data-testid={`input-inline-task-description-${index}`}
|
data-testid={`input-inline-task-description-${index}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<label className="text-xs font-medium text-muted-foreground">Priority</label>
|
<label className="text-xs font-medium text-muted-foreground">{t('projectTemplate.priority')}</label>
|
||||||
<Select
|
<Select
|
||||||
value={taskForm.priority || 'medium'}
|
value={taskForm.priority || 'medium'}
|
||||||
onValueChange={(value: ProjectTask['priority']) =>
|
onValueChange={(value: ProjectTask['priority']) =>
|
||||||
@@ -1260,15 +1260,15 @@ export default function ProjectTemplate({
|
|||||||
<SelectValue />
|
<SelectValue />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="low">Low</SelectItem>
|
<SelectItem value="low">{t('priority.low')}</SelectItem>
|
||||||
<SelectItem value="medium">Medium</SelectItem>
|
<SelectItem value="medium">{t('priority.medium')}</SelectItem>
|
||||||
<SelectItem value="high">High</SelectItem>
|
<SelectItem value="high">{t('priority.high')}</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<label className="text-xs font-medium text-muted-foreground">Status</label>
|
<label className="text-xs font-medium text-muted-foreground">{t('projectTemplate.status')}</label>
|
||||||
<Select
|
<Select
|
||||||
value={taskForm.status || 'todo'}
|
value={taskForm.status || 'todo'}
|
||||||
onValueChange={(value: ProjectTask['status']) =>
|
onValueChange={(value: ProjectTask['status']) =>
|
||||||
@@ -1279,15 +1279,15 @@ export default function ProjectTemplate({
|
|||||||
<SelectValue />
|
<SelectValue />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value="todo">To Do</SelectItem>
|
<SelectItem value="todo">{t('status.todo')}</SelectItem>
|
||||||
<SelectItem value="inProgress">In Progress</SelectItem>
|
<SelectItem value="inProgress">{t('status.inProgress')}</SelectItem>
|
||||||
<SelectItem value="done">Done</SelectItem>
|
<SelectItem value="done">{t('status.done')}</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-1 md:col-span-2">
|
<div className="space-y-1 md:col-span-2">
|
||||||
<label className="text-xs font-medium text-muted-foreground">Estimated Hours</label>
|
<label className="text-xs font-medium text-muted-foreground">{t('projectTemplate.estimatedHours')}</label>
|
||||||
<Input
|
<Input
|
||||||
type="number"
|
type="number"
|
||||||
value={taskForm.estimatedHours || ''}
|
value={taskForm.estimatedHours || ''}
|
||||||
@@ -1307,7 +1307,7 @@ export default function ProjectTemplate({
|
|||||||
onClick={handleCancelTaskEdit}
|
onClick={handleCancelTaskEdit}
|
||||||
data-testid={`button-cancel-inline-edit-${index}`}
|
data-testid={`button-cancel-inline-edit-${index}`}
|
||||||
>
|
>
|
||||||
Cancel
|
{t('projectTemplate.cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -1315,7 +1315,7 @@ export default function ProjectTemplate({
|
|||||||
disabled={!taskForm.title?.trim()}
|
disabled={!taskForm.title?.trim()}
|
||||||
data-testid={`button-save-inline-edit-${index}`}
|
data-testid={`button-save-inline-edit-${index}`}
|
||||||
>
|
>
|
||||||
Save Changes
|
{t('projectTemplate.save')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1345,13 +1345,13 @@ export default function ProjectTemplate({
|
|||||||
) : null}
|
) : null}
|
||||||
{task.timeTracked && task.timeTracked > 0 && (
|
{task.timeTracked && task.timeTracked > 0 && (
|
||||||
<Badge variant="outline" className="text-xs bg-blue-50 text-blue-700 border-blue-200">
|
<Badge variant="outline" className="text-xs bg-blue-50 text-blue-700 border-blue-200">
|
||||||
{Math.floor(task.timeTracked / 60)}h {task.timeTracked % 60}m tracked
|
{Math.floor(task.timeTracked / 60)}h {task.timeTracked % 60}m {t('projectTemplate.tracked')}
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
{task.notes && task.notes.trim() && (
|
{task.notes && task.notes.trim() && (
|
||||||
<Badge variant="outline" className="text-xs bg-green-50 text-green-700 border-green-200">
|
<Badge variant="outline" className="text-xs bg-green-50 text-green-700 border-green-200">
|
||||||
<FileText className="w-3 h-3 mr-1" />
|
<FileText className="w-3 h-3 mr-1" />
|
||||||
Notes
|
{t('projectTemplate.notesLabel')}
|
||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -1365,7 +1365,7 @@ export default function ProjectTemplate({
|
|||||||
handleOpenTaskDetails(task);
|
handleOpenTaskDetails(task);
|
||||||
}}
|
}}
|
||||||
data-testid={`button-details-task-${index}`}
|
data-testid={`button-details-task-${index}`}
|
||||||
title="View task details"
|
title={t('projectTemplate.viewTaskDetails')}
|
||||||
>
|
>
|
||||||
<FileText className="w-3 h-3" />
|
<FileText className="w-3 h-3" />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1377,7 +1377,7 @@ export default function ProjectTemplate({
|
|||||||
handleEditTask(index);
|
handleEditTask(index);
|
||||||
}}
|
}}
|
||||||
data-testid={`button-edit-task-edit-${index}`}
|
data-testid={`button-edit-task-edit-${index}`}
|
||||||
title="Edit task"
|
title={t('projectTemplate.editTaskTooltip')}
|
||||||
>
|
>
|
||||||
<Edit className="w-3 h-3" />
|
<Edit className="w-3 h-3" />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1389,7 +1389,7 @@ export default function ProjectTemplate({
|
|||||||
handleRemoveTask(index);
|
handleRemoveTask(index);
|
||||||
}}
|
}}
|
||||||
data-testid={`button-remove-task-edit-${index}`}
|
data-testid={`button-remove-task-edit-${index}`}
|
||||||
title="Remove task"
|
title={t('projectTemplate.removeTask')}
|
||||||
>
|
>
|
||||||
<Trash2 className="w-3 h-3" />
|
<Trash2 className="w-3 h-3" />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1401,7 +1401,7 @@ export default function ProjectTemplate({
|
|||||||
|
|
||||||
{projectTasks.length === 0 && (
|
{projectTasks.length === 0 && (
|
||||||
<div className="text-center text-muted-foreground text-sm py-8 border-2 border-dashed border-muted rounded-lg">
|
<div className="text-center text-muted-foreground text-sm py-8 border-2 border-dashed border-muted rounded-lg">
|
||||||
No tasks in this project yet. Click "Add Task" to get started.
|
{t('projectTemplate.noTasksInProject')}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -253,7 +253,14 @@
|
|||||||
"projectDescriptionPlaceholder": "Projektbeschreibung eingeben (optional)",
|
"projectDescriptionPlaceholder": "Projektbeschreibung eingeben (optional)",
|
||||||
"plannedEndDate": "Geplantes Enddatum",
|
"plannedEndDate": "Geplantes Enddatum",
|
||||||
"selectPlannedEndDate": "Geplantes Enddatum wählen",
|
"selectPlannedEndDate": "Geplantes Enddatum wählen",
|
||||||
"clearDate": "Datum löschen"
|
"clearDate": "Datum löschen",
|
||||||
|
"noTasksInProject": "Noch keine Aufgaben in diesem Projekt. Klicken Sie auf \"Aufgabe hinzufügen\", um zu beginnen.",
|
||||||
|
"closedProjects": "Abgeschlossene Projekte",
|
||||||
|
"viewTaskDetails": "Aufgabendetails anzeigen",
|
||||||
|
"editTaskTooltip": "Aufgabe bearbeiten",
|
||||||
|
"removeTask": "Aufgabe entfernen",
|
||||||
|
"tracked": "verfolgt",
|
||||||
|
"notesLabel": "Notizen"
|
||||||
},
|
},
|
||||||
"timeCompletion": {
|
"timeCompletion": {
|
||||||
"title": "Aufgabe abgeschlossen!",
|
"title": "Aufgabe abgeschlossen!",
|
||||||
|
|||||||
@@ -253,7 +253,14 @@
|
|||||||
"projectDescriptionPlaceholder": "Enter project description (optional)",
|
"projectDescriptionPlaceholder": "Enter project description (optional)",
|
||||||
"plannedEndDate": "Planned End Date",
|
"plannedEndDate": "Planned End Date",
|
||||||
"selectPlannedEndDate": "Select planned end date",
|
"selectPlannedEndDate": "Select planned end date",
|
||||||
"clearDate": "Clear date"
|
"clearDate": "Clear date",
|
||||||
|
"noTasksInProject": "No tasks in this project yet. Click \"Add Task\" to get started.",
|
||||||
|
"closedProjects": "Closed Projects",
|
||||||
|
"viewTaskDetails": "View task details",
|
||||||
|
"editTaskTooltip": "Edit task",
|
||||||
|
"removeTask": "Remove task",
|
||||||
|
"tracked": "tracked",
|
||||||
|
"notesLabel": "Notes"
|
||||||
},
|
},
|
||||||
"timeCompletion": {
|
"timeCompletion": {
|
||||||
"title": "Task Completed!",
|
"title": "Task Completed!",
|
||||||
|
|||||||
Reference in New Issue
Block a user