From 6e301e2928866cd354b7d736a958577361da83c8 Mon Sep 17 00:00:00 2001 From: Michelle Date: Wed, 4 Mar 2026 08:57:21 +0100 Subject: [PATCH] feat(notfound): add NotFound page with 404 handling and localization --- src/App.jsx | 5 ++-- src/i18n/de.json | 8 +++++- src/i18n/en.json | 6 +++++ src/pages/NotFound.jsx | 59 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 src/pages/NotFound.jsx diff --git a/src/App.jsx b/src/App.jsx index 6810bb8..1000716 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -18,6 +18,7 @@ import FederationInbox from './pages/FederationInbox'; import FederatedRoomDetail from './pages/FederatedRoomDetail'; import Calendar from './pages/Calendar'; import OAuthCallback from './pages/OAuthCallback'; +import NotFound from './pages/NotFound'; export default function App() { const { user, loading } = useAuth(); @@ -65,8 +66,8 @@ export default function App() { } /> - {/* Catch all */} - } /> + {/* 404 */} + } /> ); } diff --git a/src/i18n/de.json b/src/i18n/de.json index cc0bcee..8fa3b50 100644 --- a/src/i18n/de.json +++ b/src/i18n/de.json @@ -412,7 +412,7 @@ "oauthClientSecret": "Client-Secret", "oauthClientSecretHint": "Leer lassen, um das bestehende Secret beizubehalten", "oauthDisplayName": "Button-Beschriftung", - "oauthDisplayNameHint": "Wird auf der Login-Seite angezeigt, z. B. „Firmen-SSO"", + "oauthDisplayNameHint": "Wird auf der Login-Seite angezeigt, z. B. Firmen-SSO", "oauthAutoRegister": "Neue Benutzer automatisch registrieren", "oauthAutoRegisterHint": "Erstellt automatisch Konten für Benutzer, die sich zum ersten Mal per OAuth anmelden.", "oauthSaved": "OAuth-Konfiguration gespeichert", @@ -588,5 +588,11 @@ "note": "Der Termin wurde automatisch aus deinem Kalender entfernt.", "footer": "Diese Nachricht wurde automatisch von {appName} versendet." } + }, + "notFound": { + "title": "Seite nicht gefunden", + "description": "Die Seite, die du suchst, existiert nicht oder wurde verschoben.", + "goBack": "Zurück", + "goHome": "Zur Startseite" } } \ No newline at end of file diff --git a/src/i18n/en.json b/src/i18n/en.json index 56ea247..f58b4eb 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -588,5 +588,11 @@ "note": "The event has been automatically removed from your calendar.", "footer": "This message was sent automatically by {appName}." } + }, + "notFound": { + "title": "Page not found", + "description": "The page you are looking for doesn't exist or has been moved.", + "goBack": "Go back", + "goHome": "Back to home" } } \ No newline at end of file diff --git a/src/pages/NotFound.jsx b/src/pages/NotFound.jsx new file mode 100644 index 0000000..f01d4f4 --- /dev/null +++ b/src/pages/NotFound.jsx @@ -0,0 +1,59 @@ +import { Link } from 'react-router-dom'; +import { useLanguage } from '../contexts/LanguageContext'; +import { Ghost, ArrowLeft, Home } from 'lucide-react'; + +export default function NotFound() { + const { t } = useLanguage(); + + return ( +
+ {/* Animated background */} +
+
+
+
+
+
+ +
+
+ {/* Ghost icon with subtle animation */} +
+
+ +
+
+ + {/* 404 number */} +

404

+ +

+ {t('notFound.title')} +

+ +

+ {t('notFound.description')} +

+ + {/* Action buttons */} +
+ + + + {t('notFound.goHome')} + +
+
+
+
+ ); +}