3fefc550fe
- Django backend with DRF (clubs, wrestlers, trainers, exercises, templates, trainings, homework, locations, leistungstest) - Next.js 16 frontend with React, Shadcn UI, Tailwind - JWT authentication - Full CRUD for all entities - Calendar view for trainings - Homework management system - Leistungstest tracking
52 lines
1.1 KiB
TypeScript
52 lines
1.1 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useState } from "react"
|
|
import { useRouter, usePathname } from "next/navigation"
|
|
import { useAuth } from "@/lib/auth"
|
|
import { Loader2 } from "lucide-react"
|
|
import { Sidebar } from "@/components/layout/Sidebar"
|
|
|
|
export default function DashboardLayout({
|
|
children,
|
|
}: {
|
|
children: React.ReactNode
|
|
}) {
|
|
const router = useRouter()
|
|
const pathname = usePathname()
|
|
const { token, isHydrated } = useAuth()
|
|
const [checked, setChecked] = useState(false)
|
|
|
|
useEffect(() => {
|
|
if (!isHydrated) return
|
|
|
|
if (!token) {
|
|
router.push("/login")
|
|
} else {
|
|
setChecked(true)
|
|
}
|
|
}, [isHydrated, token, router])
|
|
|
|
if (!isHydrated || !checked) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center bg-background">
|
|
<Loader2 className="w-8 h-8 animate-spin text-primary" />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (!token) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div className="flex min-h-screen bg-background">
|
|
<Sidebar />
|
|
<main className="flex-1 min-h-screen">
|
|
<div className="p-8 h-full">
|
|
{children}
|
|
</div>
|
|
</main>
|
|
</div>
|
|
)
|
|
}
|