diff --git a/src/app/app/onboarding/page.tsx b/src/app/app/onboarding/page.tsx index 523dcc1..adcdbfb 100644 --- a/src/app/app/onboarding/page.tsx +++ b/src/app/app/onboarding/page.tsx @@ -3,7 +3,7 @@ import Link from 'next/link'; import { redirect } from 'next/navigation'; import { twMerge } from 'tailwind-merge'; import { buttonGreenClassName } from '@/modules/shared/control/button/buttonClassName'; -import { ErrorList } from '@/modules/shared/errors/ErrorList'; +import { ErrorList } from '@/modules/shared/error/ErrorList'; import { getProjects } from '@/modules/app/projects/ProjectsRepository'; export default async function OnboardingPage() { diff --git a/src/app/auth/error.tsx b/src/app/auth/error.tsx index 6ddc411..dec8c6d 100644 --- a/src/app/auth/error.tsx +++ b/src/app/auth/error.tsx @@ -1,6 +1,6 @@ 'use client'; -import { DefaultError } from '@/modules/shared/errors/DefaultError'; +import { DefaultError } from '@/modules/shared/error/DefaultError'; export default function AuthError({ error, reset }: { error: Error; reset: () => void }) { return ; diff --git a/src/app/error.tsx b/src/app/error.tsx index 9946ebe..d670099 100644 --- a/src/app/error.tsx +++ b/src/app/error.tsx @@ -1,6 +1,6 @@ 'use client'; -import { DefaultError } from '@/modules/shared/errors/DefaultError'; +import { DefaultError } from '@/modules/shared/error/DefaultError'; export default function RootError({ error, reset }: { error: Error; reset: () => void }) { return ; diff --git a/src/modules/app/projects/NoTasksInProject.tsx b/src/modules/app/projects/NoTasksInProject.tsx index 6d54a61..82623b6 100644 --- a/src/modules/app/projects/NoTasksInProject.tsx +++ b/src/modules/app/projects/NoTasksInProject.tsx @@ -1,4 +1,4 @@ -import { ErrorList } from '@/modules/shared/errors/ErrorList'; +import { ErrorList } from '@/modules/shared/error/ErrorList'; import { getTasks } from '@/modules/app/tasks/TasksRepository'; interface NoTasksInProjectProps { diff --git a/src/modules/app/projects/ProjectForm.tsx b/src/modules/app/projects/ProjectForm.tsx index f2c3337..0d61b77 100644 --- a/src/modules/app/projects/ProjectForm.tsx +++ b/src/modules/app/projects/ProjectForm.tsx @@ -6,7 +6,7 @@ import { buttonGreenClassName } from '@/modules/shared/control/button/buttonClas import { SubmitButton } from '@/modules/shared/control/button/SubmitButton'; import { inputTextClassName } from '@/modules/shared/control/input/inputTextClassName'; import { ServerError } from '@/modules/shared/data-access/ServerResponse'; -import { ErrorList } from '@/modules/shared/errors/ErrorList'; +import { ErrorList } from '@/modules/shared/error/ErrorList'; import { Form } from '@/modules/shared/form/Form'; import { FormErrorList } from '@/modules/shared/form/FormErrorList'; import { ProjectDto, createProject, getProjectById, updateProject } from './ProjectsRepository'; diff --git a/src/modules/app/projects/ProjectList.tsx b/src/modules/app/projects/ProjectList.tsx index 6994de3..de39537 100644 --- a/src/modules/app/projects/ProjectList.tsx +++ b/src/modules/app/projects/ProjectList.tsx @@ -3,7 +3,7 @@ import 'server-only'; import { twMerge } from 'tailwind-merge'; import { ClassNamePropsOptional } from '@/modules/shared/ClassNameProps'; -import { ErrorList } from '@/modules/shared/errors/ErrorList'; +import { ErrorList } from '@/modules/shared/error/ErrorList'; import { ProjectListItem } from './ProjectListItem'; import { ProjectStatus } from './ProjectStatus'; import { getProjects } from './ProjectsRepository'; diff --git a/src/modules/app/projects/ProjectPageHeader.tsx b/src/modules/app/projects/ProjectPageHeader.tsx index d5cf03c..98e4a07 100644 --- a/src/modules/app/projects/ProjectPageHeader.tsx +++ b/src/modules/app/projects/ProjectPageHeader.tsx @@ -2,7 +2,7 @@ import { notFound } from 'next/navigation'; import { getProjectById } from './ProjectsRepository'; import { ProjectMutationDropdown } from './ProjectMutationDropdown'; import { WarningFeedback } from '@/modules/shared/feedback/WarningFeedback'; -import { ErrorList } from '@/modules/shared/errors/ErrorList'; +import { ErrorList } from '@/modules/shared/error/ErrorList'; export interface ProjectPageHeaderProps { readonly id: string; diff --git a/src/modules/app/projects/ProjectsRepository.ts b/src/modules/app/projects/ProjectsRepository.ts index 5676dcf..6338aa3 100644 --- a/src/modules/app/projects/ProjectsRepository.ts +++ b/src/modules/app/projects/ProjectsRepository.ts @@ -10,7 +10,7 @@ import { createServerErrorResponse, createServerSuccessResponse, } from '@/modules//shared/data-access/ServerResponse'; -import { genericAwareOfInternalErrorMessage } from '@/modules/app//shared/errors/errorMessages'; +import { genericAwareOfInternalErrorMessage } from '@/modules/app//shared/error/errorMessages'; import { getServerSideUser } from '@/modules/app/users/UsersRepository'; import { createProjectSchema, deleteProjectSchema, updateProjectSchema } from './ProjectsDomain'; diff --git a/src/modules/app/projects/ProjectsSelect.tsx b/src/modules/app/projects/ProjectsSelect.tsx index fa8d7ec..a2e4941 100644 --- a/src/modules/app/projects/ProjectsSelect.tsx +++ b/src/modules/app/projects/ProjectsSelect.tsx @@ -1,7 +1,7 @@ import 'server-only'; import { ProjectDto, getProjects } from '@/modules/app/projects/ProjectsRepository'; import { Select, SelectItemProps, SelectProps } from '@/modules/shared/control/select/Select'; -import { ErrorList } from '@/modules/shared/errors/ErrorList'; +import { ErrorList } from '@/modules/shared/error/ErrorList'; export type ProjectsSelectProps = Omit; diff --git a/src/modules/app/shared/errors/errorMessages.ts b/src/modules/app/shared/error/errorMessages.ts similarity index 100% rename from src/modules/app/shared/errors/errorMessages.ts rename to src/modules/app/shared/error/errorMessages.ts diff --git a/src/modules/app/tasks/DeleteTaskAlertDialog.tsx b/src/modules/app/tasks/DeleteTaskAlertDialog.tsx index 28281a3..a9ad8f2 100644 --- a/src/modules/app/tasks/DeleteTaskAlertDialog.tsx +++ b/src/modules/app/tasks/DeleteTaskAlertDialog.tsx @@ -1,7 +1,7 @@ import 'server-only'; import { notFound } from 'next/navigation'; import { AlertDialog, AlertDialogBody } from '@/modules/shared/dialog/AlertDialog'; -import { ErrorList } from '@/modules/shared/errors/ErrorList'; +import { ErrorList } from '@/modules/shared/error/ErrorList'; import { Form } from '@/modules/shared/form/Form'; import { FormErrorList } from '@/modules/shared/form/FormErrorList'; import { RouterAction } from '@/modules/shared/router/RouterActions'; diff --git a/src/modules/app/tasks/TaskForm.tsx b/src/modules/app/tasks/TaskForm.tsx index 3d5b5b7..856b28d 100644 --- a/src/modules/app/tasks/TaskForm.tsx +++ b/src/modules/app/tasks/TaskForm.tsx @@ -3,7 +3,7 @@ import { notFound } from 'next/navigation'; import { twMerge } from 'tailwind-merge'; import { ClassNamePropsOptional } from '@/modules/shared/ClassNameProps'; import { ServerError } from '@/modules/shared/data-access/ServerResponse'; -import { ErrorList } from '@/modules/shared/errors/ErrorList'; +import { ErrorList } from '@/modules/shared/error/ErrorList'; import { Form } from '@/modules/shared/form/Form'; import { FormErrorList } from '@/modules/shared/form/FormErrorList'; import { ProjectsSelect } from '@/modules/app/projects/ProjectsSelect'; diff --git a/src/modules/app/tasks/TaskList.tsx b/src/modules/app/tasks/TaskList.tsx index d59e81e..7d33f29 100644 --- a/src/modules/app/tasks/TaskList.tsx +++ b/src/modules/app/tasks/TaskList.tsx @@ -6,7 +6,7 @@ import { ClassNamePropsOptional } from '@/modules/shared/ClassNameProps'; import { getServerSideUser } from '@/modules/app/users/UsersRepository'; import { GetTasksParams, TaskDto, getTasks } from './TasksRepository'; import { TaskListItem } from './TaskListItem'; -import { ErrorList } from '@/modules/shared/errors/ErrorList'; +import { ErrorList } from '@/modules/shared/error/ErrorList'; export interface TaskListProps extends GetTasksParams, ClassNamePropsOptional { readonly children?: ({ diff --git a/src/modules/app/tasks/TasksRepository.ts b/src/modules/app/tasks/TasksRepository.ts index 50e12c6..b985eeb 100644 --- a/src/modules/app/tasks/TasksRepository.ts +++ b/src/modules/app/tasks/TasksRepository.ts @@ -13,7 +13,7 @@ import { createServerErrorResponse, createServerSuccessResponse, } from '@/modules/shared/data-access/ServerResponse'; -import { genericAwareOfInternalErrorMessage } from '@/modules/app/shared/errors/errorMessages'; +import { genericAwareOfInternalErrorMessage } from '@/modules/app/shared/error/errorMessages'; import { ProjectStatus } from '@/modules/app/projects/ProjectStatus'; import { TaskStatus } from './TaskStatus'; import { TaskOrderBy } from './TaskOrderBy'; diff --git a/src/modules/app/users/UsersRepository.ts b/src/modules/app/users/UsersRepository.ts index cfff47f..dee69b6 100644 --- a/src/modules/app/users/UsersRepository.ts +++ b/src/modules/app/users/UsersRepository.ts @@ -12,7 +12,7 @@ import { createServerErrorResponse, createServerSuccessResponse, } from '@/modules/shared/data-access/ServerResponse'; -import { genericAwareOfInternalErrorMessage } from '@/modules/app/shared/errors/errorMessages'; +import { genericAwareOfInternalErrorMessage } from '@/modules/app/shared/error/errorMessages'; export interface UserDto { readonly email: string; diff --git a/src/modules/shared/error/DefaultError.tsx b/src/modules/shared/error/DefaultError.tsx new file mode 100644 index 0000000..ecfe8f8 --- /dev/null +++ b/src/modules/shared/error/DefaultError.tsx @@ -0,0 +1,29 @@ +'use client'; + +import { useEffect } from 'react'; +import { buttonGreenClassName } from '@/modules/shared/control/button/buttonClassName'; + +export const DefaultError = ({ error, reset }: { error: Error; reset: () => void }) => { + useEffect(() => { + // Log the error to an error reporting service + console.error(error); + }, [error]); + + return ( +
+
+

Something went wrong!

+

{error.message}

+ +
+
+ ); +}; diff --git a/src/modules/shared/error/ErrorList.tsx b/src/modules/shared/error/ErrorList.tsx new file mode 100644 index 0000000..01c7f2a --- /dev/null +++ b/src/modules/shared/error/ErrorList.tsx @@ -0,0 +1,26 @@ +'use client'; + +import 'client-only'; +import { useFormStatus } from 'react-dom'; +import { twMerge } from 'tailwind-merge'; +import { ClassNamePropsOptional } from '@/modules/shared/ClassNameProps'; +import { ServerError } from '@/modules/shared/data-access/ServerResponse'; + +interface ErrorListProps extends ClassNamePropsOptional { + readonly errors: Array; +} + +export const ErrorList = ({ className, errors }: ErrorListProps) => { + const { pending } = useFormStatus(); + if (pending || !errors || errors.length < 1) return null; + + return ( +
+ {errors.map((error) => ( +

+ {error.message} +

+ ))} +
+ ); +}; diff --git a/src/modules/shared/form/FormErrorList.tsx b/src/modules/shared/form/FormErrorList.tsx index 58fb334..2757d4e 100644 --- a/src/modules/shared/form/FormErrorList.tsx +++ b/src/modules/shared/form/FormErrorList.tsx @@ -2,7 +2,7 @@ import 'client-only'; import { useContext } from 'react'; -import { ErrorList } from '@/modules/shared/errors/ErrorList'; +import { ErrorList } from '@/modules/shared/error/ErrorList'; import { FormContext } from './Form'; export const FormErrorList = () => {