diff --git a/src/application/i18n/messages/en.json b/src/application/i18n/messages/en.json
index e1b3baf2..5010264b 100644
--- a/src/application/i18n/messages/en.json
+++ b/src/application/i18n/messages/en.json
@@ -176,6 +176,7 @@
"noteSettings": "Note settings",
"marketplace": "Marketplace",
"addTool": "Add tool",
+ "error": "Error",
"notFound": "Not found",
"joinTeam": "Join",
"authorization": "Authorize",
diff --git a/src/application/router/routes.ts b/src/application/router/routes.ts
index d242dbf4..1fe9147a 100644
--- a/src/application/router/routes.ts
+++ b/src/application/router/routes.ts
@@ -179,7 +179,6 @@ const routes: RouteRecordRaw[] = [
discardTabOnLeave: true,
},
},
-
/**
* 404 page
*/
@@ -195,6 +194,22 @@ const routes: RouteRecordRaw[] = [
code: 404,
},
},
+ /**
+ * error page
+ */
+ {
+ path: '/error/:code',
+ component: ErrorPage,
+ meta: {
+ layout: 'fullpage',
+ pageTitleI18n: 'pages.error',
+ discardTabOnLeave: true,
+ },
+ props: route => ({
+ code: route.params.code,
+ customMessage: route.query.message,
+ }),
+ },
];
export default routes;
diff --git a/src/application/services/useNote.ts b/src/application/services/useNote.ts
index 938fbc0f..8afc5988 100644
--- a/src/application/services/useNote.ts
+++ b/src/application/services/useNote.ts
@@ -5,6 +5,7 @@ import type { NoteTool } from '@/domain/entities/Note';
import { useRouter, useRoute } from 'vue-router';
import type { NoteDraft } from '@/domain/entities/NoteDraft';
import type EditorTool from '@/domain/entities/EditorTool';
+import NotFoundError from '@/domain/entities/errors/NotFound';
import useHeader from './useHeader';
import { getTitle } from '@/infrastructure/utils/note';
@@ -166,12 +167,20 @@ export default function (options: UseNoteComposableOptions): UseNoteComposableSt
/**
* @todo try-catch domain errors
*/
- const response = await noteService.getNoteById(id);
-
- note.value = response.note;
- canEdit.value = response.accessRights.canEdit;
- noteTools.value = response.tools;
- parentNote.value = response.parentNote;
+ try {
+ const response = await noteService.getNoteById(id);
+
+ note.value = response.note;
+ canEdit.value = response.accessRights.canEdit;
+ noteTools.value = response.tools;
+ parentNote.value = response.parentNote;
+ } catch (error) {
+ if (error instanceof NotFoundError) {
+ void router.push(`/error/404`);
+ } else {
+ void router.push('/error/500');
+ }
+ }
}
/**
diff --git a/src/domain/entities/errors/ApiError.ts b/src/domain/entities/errors/ApiError.ts
new file mode 100644
index 00000000..0efc2987
--- /dev/null
+++ b/src/domain/entities/errors/ApiError.ts
@@ -0,0 +1,16 @@
+import DomainError from './Base';
+
+/**
+ * Domain error thrown when unknown error occurs
+ */
+export default class ApiError extends DomainError {
+ /**
+ * Constructor for ApiError error
+ * @param message - Error message
+ * @param statusCode - Error status code
+ */
+ constructor(message: string, public statusCode: number) {
+ super(message);
+ this.name = 'ApiError';
+ }
+}
diff --git a/src/infrastructure/transport/notes-api/index.ts b/src/infrastructure/transport/notes-api/index.ts
index 175a5bc8..6df6ace2 100644
--- a/src/infrastructure/transport/notes-api/index.ts
+++ b/src/infrastructure/transport/notes-api/index.ts
@@ -5,6 +5,7 @@ import AuthorizableTransport from '@/infrastructure/transport/authorizable.trans
import type JSONValue from '../types/JSONValue';
import UnauthorizedError from '@/domain/entities/errors/Unauthorized';
import NotFoundError from '@/domain/entities/errors/NotFound';
+import ApiError from '@/domain/entities/errors/ApiError';
import type { FilesDto } from '../types/FileDto';
/**
@@ -53,7 +54,7 @@ export default class NotesApiTransport extends AuthorizableTransport {
case 404:
return new NotFoundError(errorText);
default:
- return new Error(errorText);
+ return new ApiError(errorText, status);
}
},
});
diff --git a/src/presentation/pages/Error.vue b/src/presentation/pages/Error.vue
index ec704511..c22787e8 100644
--- a/src/presentation/pages/Error.vue
+++ b/src/presentation/pages/Error.vue
@@ -12,6 +12,12 @@