feat(router-with-admin): App.tsx +/admin route + Nav admin-link bei admin-role [tsc:ok]
This commit is contained in:
parent
0a3b293c62
commit
38d9258912
@ -3,8 +3,9 @@
|
|||||||
"admin-user-management",
|
"admin-user-management",
|
||||||
"csv-export-time-entries",
|
"csv-export-time-entries",
|
||||||
"error-boundary",
|
"error-boundary",
|
||||||
"dashboard-charts"
|
"dashboard-charts",
|
||||||
|
"api-client-phase4"
|
||||||
],
|
],
|
||||||
"current_feature": "api-client-phase4",
|
"current_feature": "router-with-admin",
|
||||||
"started_at": "2026-05-23T05:10:51.482879"
|
"started_at": "2026-05-23T05:10:51.482879"
|
||||||
}
|
}
|
||||||
@ -515,3 +515,15 @@ undefined
|
|||||||
- `05:17:24` **INFO** wrote 3845 chars in 34.1s (attempt 1)
|
- `05:17:24` **INFO** wrote 3845 chars in 34.1s (attempt 1)
|
||||||
- `05:17:24` **INFO** Running tsc --noEmit on api…
|
- `05:17:24` **INFO** Running tsc --noEmit on api…
|
||||||
- `05:17:26` **INFO** tsc clean ✓
|
- `05:17:26` **INFO** tsc clean ✓
|
||||||
|
- `05:17:26` **INFO** Committed feature api-client-phase4
|
||||||
|
- `05:17:26` **INFO** Pushed: rc=0
|
||||||
|
|
||||||
|
## Phase-3 Feature: router-with-admin (2026-05-23 05:17:26)
|
||||||
|
|
||||||
|
- `05:17:26` **INFO** Description: App.tsx +/admin route + Nav admin-link bei admin-role
|
||||||
|
- `05:17:26` **INFO** Generating apps/web/src/App.tsx (ERWEITERT — füge Route /admin (AdminUsers component) hinzu. Auth-Check…)
|
||||||
|
- `05:17:50` **INFO** wrote 2745 chars in 24.1s (attempt 1)
|
||||||
|
- `05:17:50` **INFO** Generating apps/web/src/components/Nav.tsx (ERWEITERT — Nav zeigt Admin-Link nur wenn current user role='admin'. u…)
|
||||||
|
- `05:18:20` **INFO** wrote 3580 chars in 29.7s (attempt 1)
|
||||||
|
- `05:18:20` **INFO** Running tsc --noEmit on api…
|
||||||
|
- `05:18:21` **INFO** tsc clean ✓
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import TimeEntries from "./pages/TimeEntries"
|
|||||||
import Customers from "./pages/Customers"
|
import Customers from "./pages/Customers"
|
||||||
import Projects from "./pages/Projects"
|
import Projects from "./pages/Projects"
|
||||||
import Profile from "./pages/Profile"
|
import Profile from "./pages/Profile"
|
||||||
|
import AdminUsers from "./pages/AdminUsers"
|
||||||
import Nav from "./components/Nav"
|
import Nav from "./components/Nav"
|
||||||
import { ToastProvider } from "./components/Toast"
|
import { ToastProvider } from "./components/Toast"
|
||||||
import ErrorBoundary from "./components/ErrorBoundary"
|
import ErrorBoundary from "./components/ErrorBoundary"
|
||||||
@ -35,6 +36,22 @@ const authCheck = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const adminCheck = async () => {
|
||||||
|
try {
|
||||||
|
const user = await api.getMe()
|
||||||
|
if (user.role !== "admin") {
|
||||||
|
throw redirect({ to: "/" })
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error.status === 401) {
|
||||||
|
throw redirect({ to: "/login" })
|
||||||
|
} else if (error.status === 302 || error.status === 403) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
throw redirect({ to: "/" })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const indexRoute = createRoute({
|
const indexRoute = createRoute({
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
path: "/",
|
path: "/",
|
||||||
@ -70,13 +87,21 @@ const profileRoute = createRoute({
|
|||||||
component: Profile
|
component: Profile
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const adminRoute = createRoute({
|
||||||
|
getParentRoute: () => rootRoute,
|
||||||
|
path: "/admin",
|
||||||
|
beforeLoad: adminCheck,
|
||||||
|
component: AdminUsers
|
||||||
|
})
|
||||||
|
|
||||||
const routeTree = rootRoute.addChildren([
|
const routeTree = rootRoute.addChildren([
|
||||||
indexRoute,
|
indexRoute,
|
||||||
loginRoute,
|
loginRoute,
|
||||||
timeEntriesRoute,
|
timeEntriesRoute,
|
||||||
customersRoute,
|
customersRoute,
|
||||||
projectsRoute,
|
projectsRoute,
|
||||||
profileRoute
|
profileRoute,
|
||||||
|
adminRoute
|
||||||
])
|
])
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
|||||||
@ -6,12 +6,19 @@ import {
|
|||||||
Users,
|
Users,
|
||||||
FolderKanban,
|
FolderKanban,
|
||||||
User,
|
User,
|
||||||
LogOut
|
LogOut,
|
||||||
|
ShieldCheck
|
||||||
} from "lucide-react"
|
} from "lucide-react"
|
||||||
|
import { useQuery } from "@tanstack/react-query"
|
||||||
import { api } from "../lib/api"
|
import { api } from "../lib/api"
|
||||||
|
|
||||||
export default function Nav() {
|
export default function Nav() {
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
|
|
||||||
|
const { data: user } = useQuery({
|
||||||
|
queryKey: ['me'],
|
||||||
|
queryFn: api.getMe
|
||||||
|
})
|
||||||
|
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ label: "Dashboard", to: "/", icon: Home },
|
{ label: "Dashboard", to: "/", icon: Home },
|
||||||
@ -60,6 +67,20 @@ export default function Nav() {
|
|||||||
</Link>
|
</Link>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
||||||
|
{user?.role === 'admin' && (
|
||||||
|
<Link
|
||||||
|
to="/admin"
|
||||||
|
className={`flex items-center gap-2 px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
||||||
|
location.pathname === "/admin"
|
||||||
|
? "bg-indigo-50 text-indigo-700"
|
||||||
|
: "text-gray-600 hover:bg-gray-50 hover:text-gray-900"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<ShieldCheck className="w-4 h-4" />
|
||||||
|
Admin
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user