From 64b240bf267b43aaf5c4408eef357ae499253487 Mon Sep 17 00:00:00 2001 From: Amirhossein Khalili Date: Sat, 6 Jun 2026 23:34:19 +0330 Subject: [PATCH] refactor(routing): isolate public and protected routes --- src/App.tsx | 71 +++++++++++++++++++++++++++--------------- src/main.tsx | 7 ++--- src/pages/NotFound.tsx | 70 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 30 deletions(-) create mode 100644 src/pages/NotFound.tsx diff --git a/src/App.tsx b/src/App.tsx index e38f078..aa34b4d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,6 +5,7 @@ import { LanguageProvider } from "./components/LanguageProvider" import { Toaster } from "./components/ui/toaster" import { Navbar } from "./components/Navbar" import { Sidebar } from './components/Sidebar'; +import { AppProvider } from "./context/AppContext" import { NotificationsProvider } from "./context/NotificationsContext" import { WorkspaceProvider } from "./context/WorkspaceContext" import Auth from "./pages/Auth" @@ -17,8 +18,6 @@ import WorkspaceDetail from "./pages/WorkspaceDetail" import EditWorkspace from "./pages/WorkspaceEdit" import Clients from "./pages/Clients" import { Projects } from "./pages/Projects" -import ProjectCreate from "./pages/ProjectCreate" -import ProjectEdit from "./pages/ProjectEdit" import Tags from "./pages/Tags" import Reports from "./pages/Reports" import Timesheet from "./pages/Timesheet" @@ -26,7 +25,10 @@ import Logs from "./pages/Logs" import NotificationsPage from "./pages/Notifications" import RateLimitPage from "./pages/RateLimit" import Landing from "./pages/Landing" +import About from "./pages/About" +import NotFound from "./pages/NotFound" import { isRateLimitActive } from "./lib/rateLimit" +import { getAccessToken } from "./lib/session" import { AuthFlowProvider } from "./context/AuthFlowContext" import { LoginMobilePage } from "./pages/auth/LoginMobilePage" import { LoginOtpPage } from "./pages/auth/LoginOtpPage" @@ -64,10 +66,18 @@ const AppRedirect = () => { return } - const isAuthenticated = !!localStorage.getItem("accessToken") + const isAuthenticated = !!getAccessToken() return isAuthenticated ? : } +const AuthenticatedRedirectGuard = () => { + return getAccessToken() ? : +} + +const AuthRequiredGuard = () => { + return getAccessToken() ? : +} + const RateLimitGuard = () => { const location = useLocation() @@ -78,27 +88,38 @@ const RateLimitGuard = () => { return } +const AuthLayout = () => ( + + + +) + +const ProtectedAppLayout = () => ( + + + + + + + +) + const router = createBrowserRouter([ + { path: "/", element: }, + { path: "/about", element: }, + { path: "/terms", element: }, + { path: "/rate-limit", element: }, { element: , children: [ + { path: "/app", element: }, + { path: "/auth/google/callback", element: }, { - element: ( - - - - ), + path: "/auth", + element: , children: [ - { path: "/", element: }, - { path: "/app", element: }, - { path: "/auth/google/callback", element: }, { - path: "/auth", - element: ( - - - - ), + element: , children: [ { index: true, element: }, { path: "login", element: }, @@ -112,10 +133,13 @@ const router = createBrowserRouter([ { path: "forgot-password/password", element: }, ], }, - { path: "/terms", element: }, - { path: "/rate-limit", element: }, + ], + }, + { + element: , + children: [ { - element: , + element: , children: [ { path: "/profile", element: }, { path: "/timesheet", element: }, @@ -129,23 +153,20 @@ const router = createBrowserRouter([ { path: "/workspaces/:id/edit", element: }, { path: "/clients", element: }, { path: "/projects", element: }, - { path: "/projects/create", element: }, - { path: "/projects/:id/edit", element: }, ], }, ], }, ], }, + { path: "*", element: }, ]); function App() { return ( - - - + diff --git a/src/main.tsx b/src/main.tsx index 189c13d..2339d59 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,13 +1,10 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; -import { AppProvider } from './context/AppContext'; import './index.css'; ReactDOM.createRoot(document.getElementById('root')!).render( - - - + -); \ No newline at end of file +); diff --git a/src/pages/NotFound.tsx b/src/pages/NotFound.tsx new file mode 100644 index 0000000..b7e2db0 --- /dev/null +++ b/src/pages/NotFound.tsx @@ -0,0 +1,70 @@ +import { Link, useLocation } from "react-router-dom" +import { ArrowLeft, ArrowRight, Command, Compass, Home } from "lucide-react" + +import { Button } from "../components/ui/button" +import { useTranslation } from "../hooks/useTranslation" +import { cn } from "../lib/utils" + +export default function NotFound() { + const location = useLocation() + const { lang, t } = useTranslation() + const isFa = lang === "fa" + + return ( +
+
+
+ +
+
+
+
+
+ + {isFa ? "مسیر پیدا نشد" : "Route not found"} +
+

+ 404 +

+

+ {isFa + ? "این آدرس در رابط کاربری Qlockify تعریف نشده است." + : "This endpoint is not defined in the Qlockify interface."} +

+
+ {location.pathname} +
+
+ +
+ + +
+
+
+
+
+ ) +}