Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions packages/web/src/common/utils/i18n/locales/en/tasks.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
{
"addTask": "Add a new task",
"editTask": "Edit task",
"add-task": "Add a new task",
"create-task": "Create task",
"created-task": "Task created.",
"delete-task": "Delete task",
"edit-task": "Edit task",
"errors": {
"not-found": "Not found",
"unable-to-find-task": "We're unable to find the task you requested."
},
"go-back-to-task-list": "Go back to task list",
"label": {
"title": "Title",
"completed": "Is complete"
"assignee": "Assignee",
"completed": "Is complete",
"status": "Status",
"title": "Title"
},
"createdTask": "Task created.",
"markComplete": "Mark complete",
"markIncomplete": "Mark incomplete",
"markedComplete": "Marked task complete",
"markedIncomplete": "Marked task incomplete",
"list-tasks": "List tasks",
"mark-complete": "Mark complete",
"mark-incomplete": "Mark incomplete",
"marked-complete": "Marked task complete",
"marked-incomplete": "Marked task incomplete",
"marking-complete": "Marking task complete...",
"marking-incomplete": "Marking task incomplete...",
"status": {
Expand All @@ -20,6 +30,7 @@
"task": "Task",
"tasks": "Tasks",
"tasks-empty": "Nothing to do. Create a task to get started.",
"updatedTask": "Task updated.",
"update-failed": "Failed to update task. Detail: {{message}}"
"updated-task": "Task updated.",
"update-failed": "Failed to update task. Detail: {{message}}",
"view-task": "View task"
}
33 changes: 22 additions & 11 deletions packages/web/src/common/utils/i18n/locales/es/tasks.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
{
"addTask": "Crear una nueva tarea",
"editTask": "Editar tarea",
"add-task": "Crear una nueva tarea",
"create-task": "Crear tarea",
"created-task": "Tarea creada.",
"delete-task": "Eliminar tarea",
"edit-task": "Editar tarea",
"errors": {
"not-found": "No encontrado",
"unable-to-find-task": "No podemos encontrar la tarea que solicitaste."
},
"go-back-to-task-list": "Volver a la lista de tareas",
"label": {
"title": "Título",
"completed": "Está completo"
"assignee": "Asignado a",
"completed": "Está completo",
"status": "Estado",
"title": "Título"
},
"createdTask": "Tarea creada.",
"markComplete": "Márcalo completo",
"markIncomplete": "Márcalo como incompleto",
"markedComplete": "Tarea marcada completada",
"markedIncomplete": "Tarea marcada como incompleta",
"list-tasks": "Listar tareas",
"mark-complete": "Márcalo completo",
"mark-incomplete": "Márcalo como incompleto",
"marked-complete": "Tarea marcada completada",
"marked-incomplete": "Tarea marcada como incompleta",
"marking-complete": "Marcando la tarea como completada...",
"marking-incomplete": "Marcando la tarea como incompleta...",
"status": {
Expand All @@ -20,6 +30,7 @@
"task": "Tarea",
"tasks": "Tareas",
"tasks-empty": "No hay nada que hacer. Haz una tarea para empezar.",
"updatedTask": "Tarea actualizada.",
"update-failed": "Error al actualizar la tarea. Detalle: {{message}}"
"updated-task": "Tarea actualizada.",
"update-failed": "Error al actualizar la tarea. Detalle: {{message}}",
"view-task": "Ver tarea"
}
33 changes: 22 additions & 11 deletions packages/web/src/common/utils/i18n/locales/fr/tasks.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
{
"addTask": "Créer une nouvelle tâche",
"editTask": "Modifier la tâche",
"add-task": "Créer une nouvelle tâche",
"create-task": "Créer la tâche",
"created-task": "Tâche créée.",
"delete-task": "Supprimer la tâche",
"edit-task": "Modifier la tâche",
"errors": {
"not-found": "Non trouvé",
"unable-to-find-task": "Nous ne pouvons pas trouver la tâche que vous avez demandée."
},
"go-back-to-task-list": "Retour à la liste des tâches",
"label": {
"title": "Titre",
"completed": "Est complet"
"assignee": "Assigné à",
"completed": "Est complet",
"status": "Statut",
"title": "Titre"
},
"createdTask": "Tâche créée.",
"markComplete": "Marquez-le comme terminé",
"markIncomplete": "Marquez-le comme incomplet",
"markedComplete": "Tâche marquée terminée",
"markedIncomplete": "Tâche marquée incomplète",
"list-tasks": "Lister les tâches",
"mark-complete": "Marquez-le comme terminé",
"mark-incomplete": "Marquez-le comme incomplet",
"marked-complete": "Tâche marquée terminée",
"marked-incomplete": "Tâche marquée incomplète",
"marking-complete": "Marquage de la tâche comme terminée...",
"marking-incomplete": "Marquage de la tâche comme incomplète...",
"status": {
Expand All @@ -20,6 +30,7 @@
"task": "Tâche",
"tasks": "Tâches",
"tasks-empty": "Rien à faire. Créez une tâche pour commencer.",
"updatedTask": "Tâche mise à jour.",
"update-failed": "Échec de la mise à jour de la tâche. Détail : {{message}}"
"updated-task": "Tâche mise à jour.",
"update-failed": "Échec de la mise à jour de la tâche. Détail : {{message}}",
"view-task": "Voir la tâche"
}
8 changes: 4 additions & 4 deletions packages/web/src/pages/Settings/SettingsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Link, Outlet } from 'react-router-dom';
import { NavLink, Outlet } from 'react-router-dom';
import { Palette } from 'lucide-react';

import { Page } from '@react-starter/shared/components/Content/Page';
Expand All @@ -8,7 +8,7 @@ import { Skeleton } from '@react-starter/shared/components/shadcn/skeleton';
import { Avatar, AvatarFallback } from '@react-starter/shared/components/shadcn/avatar';

import { useGetCurrentUser } from '@/common/api/useGetCurrentUser';
import SettingsPageBreadcrumbs from '@/pages/Settings/components/SettingsPageBreadcrumbs';
import { SettingsPageBreadcrumbs } from '@/pages/Settings/components/SettingsPageBreadcrumbs';
import { Button } from '@react-starter/shared/components/shadcn/button';

/**
Expand Down Expand Up @@ -44,10 +44,10 @@ const SettingsPage = () => {
<ul className="*:not-last:mb-1">
<li>
<Button variant="ghost" className="w-full justify-start" asChild>
<Link to="appearance" aria-label="Appearance Settings">
<NavLink to="appearance" aria-label="Appearance Settings">
<Palette />
Appearance
</Link>
</NavLink>
</Button>
</li>
</ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Navigate, Route, Routes } from 'react-router-dom';

import { render, screen } from '@/test/test-utils';

import SettingsPageBreadcrumbs from './SettingsPageBreadcrumbs';
import { SettingsPageBreadcrumbs } from './SettingsPageBreadcrumbs';

describe('SettingsPageBreadcrumbs', () => {
it('should render successfully', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ const SettingsPageBreadcrumbs = ({ className, testId = 'page-settings-breadcrumb
<>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage className="capitalize" data-testid={`${testId}-page-${pathElements[3]}`}>
<BreadcrumbPage
className="max-w-40 truncate capitalize"
data-testid={`${testId}-page-${pathElements[3]}`}
>
{pathElements[3].replace('-', ' ')}
</BreadcrumbPage>
</BreadcrumbItem>
Expand All @@ -43,4 +46,4 @@ const SettingsPageBreadcrumbs = ({ className, testId = 'page-settings-breadcrumb
);
};

export default SettingsPageBreadcrumbs;
export { SettingsPageBreadcrumbs };
2 changes: 1 addition & 1 deletion packages/web/src/pages/Tasks/TasksPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Page } from '@react-starter/shared/components/Content/Page';
import { Container } from '@react-starter/shared/components/Content/Container';
import { Heading } from '@react-starter/shared/components/Text/Heading';

import TasksPageBreadcrumbs from '@/pages/Tasks/components/TasksPageBreadcrumbs';
import { TasksPageBreadcrumbs } from '@/pages/Tasks/components/TasksPageBreadcrumbs';
import { AddTaskButton } from '@/pages/Tasks/components/Add/AddTaskButton';

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ const AddTaskButton = ({ ...props }: React.ComponentProps<typeof Button>) => {
return (
<Tooltip>
<TooltipTrigger asChild>
<Button variant="outline" size="icon" aria-label={t('addTask', { ns: 'tasks' })} {...props}>
<Button variant="outline" size="icon" aria-label={t('add-task', { ns: 'tasks' })} {...props}>
<Link to="/app/tasks/add">
<Plus />
</Link>
</Button>
</TooltipTrigger>
<TooltipContent>{t('addTask', { ns: 'tasks' })}</TooltipContent>
<TooltipContent>{t('add-task', { ns: 'tasks' })}</TooltipContent>
</Tooltip>
);
};
Expand Down
4 changes: 2 additions & 2 deletions packages/web/src/pages/Tasks/components/Add/TaskAdd.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const TaskAdd = ({ className, testId = 'task-add' }: BaseComponentProps) => {
{ task: data },
{
onSuccess: () => {
toast(t('createdTask', { ns: 'tasks' }));
toast(t('created-task', { ns: 'tasks' }));
navigate(-1);
},
onError: (err) => {
Expand All @@ -59,7 +59,7 @@ const TaskAdd = ({ className, testId = 'task-add' }: BaseComponentProps) => {
<div className={className} data-testid={testId}>
{/* heading */}
<Heading level={2} className="mb-4">
{t('addTask', { ns: 'tasks' })}
{t('add-task', { ns: 'tasks' })}
</Heading>

{/* error state */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
DialogDescription,
DialogFooter,
} from '@react-starter/shared/components/shadcn/dialog';
import { Tooltip, TooltipTrigger, TooltipContent } from '@react-starter/shared/components/shadcn/tooltip';
import { toast } from '@react-starter/shared/components/shadcn/sonner';
import { ErrorAlert } from '@react-starter/shared/components/Alert/ErrorAlert';

Expand Down Expand Up @@ -67,9 +68,14 @@ const TaskDeleteDialog = ({ onSuccess, task, trigger, ...props }: TaskDeleteDial
return (
<Dialog {...props}>
{trigger && (
<DialogTrigger data-testid={`task-delete-dialog-trigger-${task.id}`} asChild>
{trigger}
</DialogTrigger>
<Tooltip>
<TooltipTrigger asChild>
<DialogTrigger data-testid={`task-delete-dialog-trigger-${task.id}`} asChild>
{trigger}
</DialogTrigger>
</TooltipTrigger>
<TooltipContent>{t('delete-task', { ns: 'tasks' })}</TooltipContent>
</Tooltip>
)}
<DialogContent>
<DialogHeader>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ interface TaskCompleteToggleProps extends BaseComponentProps {
* to toggle the value of the Task `complete` attribute.
* @param {TaskCompleteToggleProps} props - Component properties.
*/
export const TaskCompleteToggle = ({ className, task, testId = 'toggle-task-complete' }: TaskCompleteToggleProps) => {
const TaskCompleteToggle = ({ className, task, testId = 'toggle-task-complete' }: TaskCompleteToggleProps) => {
const { t } = useTranslation();
const { mutate: updateTask, isPending } = useUpdateTask();

const buttonTitle = task.completed ? t('markIncomplete', { ns: 'tasks' }) : t('markComplete', { ns: 'tasks' });
const buttonTitle = task.completed ? t('mark-incomplete', { ns: 'tasks' }) : t('mark-complete', { ns: 'tasks' });

/**
* Actions to perform when the task complete toggle button is clicked.
Expand All @@ -41,7 +41,7 @@ export const TaskCompleteToggle = ({ className, task, testId = 'toggle-task-comp
},
{
onSuccess: (data) => {
toast(data.completed ? t('markedComplete', { ns: 'tasks' }) : t('markedIncomplete', { ns: 'tasks' }));
toast(data.completed ? t('marked-complete', { ns: 'tasks' }) : t('marked-incomplete', { ns: 'tasks' }));
},
},
);
Expand All @@ -61,3 +61,5 @@ export const TaskCompleteToggle = ({ className, task, testId = 'toggle-task-comp
</Button>
);
};

export { TaskCompleteToggle };
4 changes: 2 additions & 2 deletions packages/web/src/pages/Tasks/components/Edit/TaskEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const TaskEdit = ({ className, testId = 'task-edit' }: BaseComponentProps) => {
{ task: updatedTask },
{
onSuccess: () => {
toast(t('updatedTask', { ns: 'tasks' }));
toast(t('updated-task', { ns: 'tasks' }));
navigate(-1);
},
onError: (err) => {
Expand All @@ -65,7 +65,7 @@ const TaskEdit = ({ className, testId = 'task-edit' }: BaseComponentProps) => {
<div className={cn(className)} data-testid={testId}>
{/* heading */}
<Heading level={2} className="mb-4">
{t('editTask', { ns: 'tasks' })}
{t('edit-task', { ns: 'tasks' })}
</Heading>

{/* loading state */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const TaskListItem = ({ task, ...props }: TaskListItemProps) => {
const updateTaskPromise = updateTaskAsync({ task: taskData });
toast.promise(updateTaskPromise, {
loading: isComplete ? t('marking-complete', { ns: 'tasks' }) : t('marking-incomplete', { ns: 'tasks' }),
success: isComplete ? t('markedComplete', { ns: 'tasks' }) : t('markedIncomplete', { ns: 'tasks' }),
success: isComplete ? t('marked-complete', { ns: 'tasks' }) : t('marked-incomplete', { ns: 'tasks' }),
error: (error) => t('update-failed', { ns: 'tasks', message: error.message }),
});
};
Expand All @@ -53,7 +53,9 @@ const TaskListItem = ({ task, ...props }: TaskListItemProps) => {
<Item variant="outline" size="xs" className="hover:bg-muted/50 hover:border-transparent" {...props}>
<ItemMedia variant="icon">{task.completed ? <CircleCheckBig /> : <Circle />}</ItemMedia>
<ItemContent>
<ItemTitle>{task.title}</ItemTitle>
<Link to={`${task.id}`} aria-label={t('view-task', { ns: 'tasks' })}>
<ItemTitle>{task.title}</ItemTitle>
</Link>
</ItemContent>
<ItemActions>
<DropdownMenu>
Expand Down
30 changes: 15 additions & 15 deletions packages/web/src/pages/Tasks/components/TaskDetailLayout.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ describe('TaskDetailLayout', () => {

it('should display a task', async () => {
// ARRANGE
render(<TaskDetailLayout testId="component" />);
await screen.findByTestId('component-task-view');
render(<TaskDetailLayout data-testid="layout-task-detail" />);
await screen.findByTestId('layout-task-detail');

// ASSERT
expect(screen.getByTestId('component-task-view')).toBeDefined();
expect(screen.getByTestId('task-view')).toBeDefined();
});

it('should display task error', async () => {
Expand All @@ -52,11 +52,11 @@ describe('TaskDetailLayout', () => {
error: new Error(),
isLoading: false,
} as unknown as UseQueryResult<Task, Error>);
render(<TaskDetailLayout testId="component" />);
await screen.findByTestId('component-error-task');
render(<TaskDetailLayout data-testid="layout-task-detail" />);
await screen.findByTestId('layout-task-detail-error');

// ASSERT
expect(screen.getByTestId('component-error-task')).toBeDefined();
expect(screen.getByTestId('layout-task-detail-error')).toBeDefined();
});

it('should render loading state', async () => {
Expand All @@ -67,21 +67,21 @@ describe('TaskDetailLayout', () => {
error: undefined,
isLoading: true,
} as unknown as UseQueryResult<Task, Error>);
render(<TaskDetailLayout testId="component" />);
await screen.findByTestId('component-loading');
render(<TaskDetailLayout data-testid="layout-task-detail" />);
await screen.findByTestId('layout-task-detail-loading');

// ASSERT
expect(screen.getByTestId('component-loading')).toBeDefined();
expect(screen.getByTestId('layout-task-detail-loading')).toBeDefined();
});

it('should navigate back using close button', async () => {
// ARRANGE
const user = userEvent.setup();
render(<TaskDetailLayout testId="component" />);
await screen.findByTestId('component-button-close');
render(<TaskDetailLayout data-testid="layout-task-detail" />);
const closeButton = await screen.findByTestId('layout-task-detail-button-close');

// ACT
await user.click(screen.getByTestId('component-button-close'));
await user.click(closeButton);

// ASSERT
expect(mockNavigate).toHaveBeenCalledTimes(1);
Expand All @@ -91,11 +91,11 @@ describe('TaskDetailLayout', () => {
it('should navigate to edit', async () => {
// ARRANGE
const user = userEvent.setup();
render(<TaskDetailLayout testId="component" />);
await screen.findByTestId('component-button-edit');
render(<TaskDetailLayout data-testid="layout-task-detail" />);
await screen.findByTestId('layout-task-detail-button-edit');

// ACT
await user.click(screen.getByTestId('component-button-edit'));
await user.click(screen.getByTestId('layout-task-detail-button-edit'));

// ASSERT
expect(mockNavigate).toHaveBeenCalledTimes(1);
Expand Down
Loading