add loading state in layout

This commit is contained in:
priyanshuvish
2025-09-03 17:22:19 +05:30
parent bf42daef0b
commit d6be8abdec
3 changed files with 41 additions and 43 deletions

View File

@@ -28,7 +28,7 @@ import { Toaster } from "./components/ui/sonner";
import { Settings } from "lucide-react";
export default function App() {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null); // null = loading
const [user, setUser] = useState({
name: "Admin User",
email: "admin@klc.edu",
@@ -41,9 +41,7 @@ export default function App() {
useEffect(() => {
const authToken = localStorage.getItem("klc_auth_token");
if (authToken) {
setIsAuthenticated(true);
}
setIsAuthenticated(!!authToken); // true if token exists, false otherwise
}, []);
const login = () => {
@@ -58,6 +56,11 @@ export default function App() {
navigate("/login");
};
if (isAuthenticated === null) {
// while checking localStorage
return <div className="flex justify-center items-center h-screen">Loading...</div>;
}
return (
<div className="min-h-screen bg-background">
<Routes>

View File

@@ -1,15 +1,15 @@
import React, { useState } from 'react';
import { Button } from '../ui/button';
import {
Home,
FileText,
GraduationCap,
Users,
Calendar,
Globe,
BarChart3,
Settings,
Menu,
import {
Home,
FileText,
GraduationCap,
Users,
Calendar,
Globe,
BarChart3,
Settings,
Menu,
ChevronLeft,
LogOut,
User,
@@ -20,7 +20,7 @@ import {
ClipboardList,
Target
} from 'lucide-react';
import {
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
@@ -29,7 +29,7 @@ import {
BreadcrumbSeparator,
} from '../ui/breadcrumb';
import { Avatar, AvatarFallback } from '../ui/avatar';
import {
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
@@ -171,19 +171,19 @@ const navigationItems: NavigationItem[] = [
}
];
export function AuthenticatedLayout({
children,
currentRoute,
// onNavigate,
onLogout,
user,
breadcrumbs = []
export function AuthenticatedLayout({
children,
currentRoute,
onLogout,
user,
breadcrumbs = []
}: AuthenticatedLayoutProps) {
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
const navigate = useNavigate(); // Move useNavigate to the top level
const isActiveRoute = (route: string) => {
return currentRoute === route ||
(route === '/users/individual' && currentRoute.startsWith('/users/'));
return currentRoute === route ||
(route === '/users/individual' && currentRoute.startsWith('/users/'));
};
const getActiveParent = (items: NavigationItem[]): string | null => {
@@ -205,27 +205,24 @@ export function AuthenticatedLayout({
const isParentActive = activeParent === item.id;
const Icon = item.icon;
const navigate = useNavigate();
return (
<div key={item.id}>
<Button
variant="ghost"
className={`w-full justify-start min-h-[44px] ${
isActive
? 'bg-primary text-primary-foreground'
className={`w-full justify-start min-h-[44px] ${isActive
? 'bg-primary text-primary-foreground'
: isParentActive && !isChild
? 'bg-accent text-accent-foreground'
: 'hover:bg-accent hover:text-accent-foreground'
} ${isChild ? 'ml-4 text-sm' : ''}`}
onClick={() => navigate(item.route)}
} ${isChild ? 'ml-4 text-sm' : ''}`}
onClick={() => navigate(item.route)} // Use the navigate from the top level
>
<Icon className={`${sidebarCollapsed ? 'mx-auto' : 'mr-2'} h-4 w-4 flex-shrink-0`} />
{!sidebarCollapsed && (
<span className="truncate">{item.label}</span>
)}
</Button>
{/* Render children if parent is active and not collapsed */}
{item.children && isParentActive && !sidebarCollapsed && (
<div className="mt-1 space-y-1">
@@ -235,11 +232,10 @@ export function AuthenticatedLayout({
</div>
);
};
const navigate = useNavigate();
return (
<div className="flex h-screen bg-background">
{/* Left Sidebar */}
<div
<div
className={`${sidebarCollapsed ? 'w-[72px]' : 'w-[240px]'} bg-sidebar border-r border-sidebar-border flex flex-col transition-all duration-200`}
role="navigation"
aria-label="Main navigation"
@@ -248,9 +244,9 @@ export function AuthenticatedLayout({
<div className="p-4 border-b border-sidebar-border" style={{ backgroundColor: 'var(--color-brand-primary)' }}>
<div className="flex items-center justify-between">
{!sidebarCollapsed && (
<img
src={klcLogoDark}
alt="Kautilya Leadership Centre"
<img
src={klcLogoDark}
alt="Kautilya Leadership Centre"
className="h-8"
/>
)}
@@ -275,7 +271,6 @@ export function AuthenticatedLayout({
{/* User Section */}
<div className="p-4 border-t border-sidebar-border"
onClick={() => navigate('/profile')}
>
<DropdownMenu>
<DropdownMenuTrigger asChild>
@@ -324,7 +319,7 @@ export function AuthenticatedLayout({
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink
<BreadcrumbLink
onClick={() => navigate('/dashboard')}
className="cursor-pointer"
>
@@ -336,7 +331,7 @@ export function AuthenticatedLayout({
<BreadcrumbSeparator />
<BreadcrumbItem>
{crumb.route && index < breadcrumbs.length - 1 ? (
<BreadcrumbLink
<BreadcrumbLink
onClick={() => navigate(crumb.route!)}
className="cursor-pointer"
>

View File

@@ -1,8 +1,8 @@
"use client";
import * as React from "react";
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu@2.1.6";
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react@0.487.0";
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
import { cn } from "./utils";