Files
portaldata/components/ui/Navbar.tsx
2025-07-15 15:18:38 +07:00

329 lines
13 KiB
TypeScript

'use client';
import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { ThemeToggle } from '@/components/theme-toggle';
import { Menu, ChevronDown, BarChart, Database, CircleCheck, School, GraduationCap, Clock, BookOpen, Award, Home, LogOut, User } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import Link from 'next/link';
import LoginDialog from './login-dialog';
import { useToast } from '@/components/ui/toast-provider';
interface UserData {
id_user: number;
username?: string;
nip?: string;
role_user: string;
}
const Navbar = () => {
const [user, setUser] = useState<UserData | null>(null);
const [isLoading, setIsLoading] = useState(true);
const { showSuccess, showError } = useToast ();
const router = useRouter();
// Check for existing user session on mount
useEffect(() => {
checkUserSession();
}, []);
const checkUserSession = async () => {
try {
const response = await fetch('/api/auth/user');
if (response.ok) {
const data = await response.json();
setUser(data.user);
}
} catch (error) {
console.error('Error checking session:', error);
} finally {
setIsLoading(false);
}
};
const handleLoginSuccess = (userData: any) => {
setUser(userData.user);
};
const handleLogout = async () => {
try {
const response = await fetch('/api/auth/logout', {
method: 'POST',
});
if (response.ok) {
setUser(null);
showSuccess("Berhasil!", "Anda telah keluar dari sistem");
// Redirect to root page after successful logout
router.push('/');
}
} catch (error) {
console.error('Logout error:', error);
showError("Gagal!", "Terjadi kesalahan saat logout");
}
};
if (isLoading) {
return (
<div className="bg-background/95 border-b py-2 sticky top-0 z-30">
<div className="container mx-auto px-4 flex justify-between items-center">
<div className="flex items-center">
<Link href="/" className="flex items-center text-lg font-semibold hover:text-primary transition-colors">
<img src="/podif-icon.png" alt="PODIF Logo" className="h-6 w-auto mr-2" />
PODIF
</Link>
</div>
<div className="flex items-center gap-4">
<ThemeToggle />
</div>
</div>
</div>
);
}
return (
<div className="bg-background/95 border-b py-2 sticky top-0 z-30">
<div className="container mx-auto px-4 flex justify-between items-center">
{/* Logo */}
<div className="flex items-center">
<Link href="/" className="flex items-center text-lg font-semibold hover:text-primary transition-colors">
<img src="/podif-icon.png" alt="PODIF Logo" className="h-6 w-auto mr-2" />
PODIF
</Link>
</div>
{/* Desktop Navigation - Centered */}
<div className="hidden md:flex items-center gap-4">
{/* Beranda - Always visible */}
<Link href="/" className="flex items-center gap-2 px-3 py-2 text-sm font-medium hover:text-primary transition-colors">
<School className="h-4 w-4" />
Beranda
</Link>
{/* Visualisasi Dropdown - Only when logged in */}
{user && (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="flex items-center gap-2 px-3 py-2 text-sm font-medium">
<BarChart className="h-4 w-4" />
Visualisasi
<ChevronDown className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="center" className="w-48">
<DropdownMenuItem asChild>
<Link href="/visualisasi/mahasiswa" className="flex items-center gap-2 w-full">
<GraduationCap className="h-4 w-4" />
Mahasiswa
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/visualisasi/status" className="flex items-center gap-2 w-full">
<CircleCheck className="h-4 w-4" />
Status Kuliah
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/visualisasi/tipekelulusan" className="flex items-center gap-2 w-full">
<Clock className="h-4 w-4" />
Tipe Kelulusan
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/visualisasi/beasiswa" className="flex items-center gap-2 w-full">
<BookOpen className="h-4 w-4" />
Beasiswa
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/visualisasi/berprestasi" className="flex items-center gap-2 w-full">
<Award className="h-4 w-4" />
Prestasi
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)}
{/* Kelola Data Dropdown - Only for Admin */}
{user && user.role_user === 'admin' && (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="flex items-center gap-2 px-3 py-2 text-sm font-medium">
<Database className="h-4 w-4" />
Kelola Data
<ChevronDown className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="center" className="w-48">
<DropdownMenuItem asChild>
<Link href="/keloladata/mahasiswa" className="flex items-center gap-2 w-full">
<GraduationCap className="h-4 w-4" />
Mahasiswa
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/keloladata/beasiswa" className="flex items-center gap-2 w-full">
<BookOpen className="h-4 w-4" />
Beasiswa
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link href="/keloladata/prestasi" className="flex items-center gap-2 w-full">
<Award className="h-4 w-4" />
Prestasi
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)}
</div>
{/* Right Side - Theme Toggle, Login/User Menu, and Mobile Menu */}
<div className="flex items-center gap-4">
{user ? (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="flex items-center gap-2">
<User className="h-4 w-4" />
{user.role_user === 'ketuajurusan' ? 'Ketua Jurusan' : 'Admin'}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem disabled>
<User className="h-4 w-4 mr-2" />
{user.role_user === 'ketuajurusan' ? user.username : user.username}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={handleLogout}>
<LogOut className="h-4 w-4 mr-2" />
Logout
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
) : (
<LoginDialog onLoginSuccess={handleLoginSuccess} />
)}
<ThemeToggle />
{/* Mobile Menu Button */}
<div className="md:hidden">
<Sheet>
<SheetTrigger asChild>
<Button variant="outline" size="icon">
<Menu className="h-5 w-5" />
<span className="sr-only">Toggle menu</span>
</Button>
</SheetTrigger>
<SheetContent side="left" className="p-0 w-[250px] overflow-y-auto">
<MobileNavContent user={user} onLogout={handleLogout} />
</SheetContent>
</Sheet>
</div>
</div>
</div>
</div>
);
};
// Mobile Navigation Content Component
interface MobileNavContentProps {
user: UserData | null;
onLogout: () => void;
}
const MobileNavContent = ({ user, onLogout }: MobileNavContentProps) => {
return (
<div className="p-4 space-y-4">
<div className="space-y-2">
<h3 className="text-sm font-semibold text-muted-foreground">Dashboard PODIF</h3>
<Link href="/" className="flex items-center gap-2 px-3 py-2 text-sm hover:bg-accent hover:text-accent-foreground rounded-md transition-colors">
<Home className="h-4 w-4" />
Beranda
</Link>
</div>
{user ? (
<div className="space-y-2">
<h3 className="text-sm font-semibold text-muted-foreground">Menu Utama</h3>
<div className="space-y-1">
<h4 className="text-xs font-medium text-muted-foreground px-3">Visualisasi</h4>
<Link href="/visualisasi/mahasiswa" className="flex items-center gap-2 px-3 py-2 text-sm hover:bg-accent hover:text-accent-foreground rounded-md transition-colors">
<GraduationCap className="h-4 w-4" />
Mahasiswa
</Link>
<Link href="/visualisasi/status" className="flex items-center gap-2 px-3 py-2 text-sm hover:bg-accent hover:text-accent-foreground rounded-md transition-colors">
<GraduationCap className="h-4 w-4" />
Status Kuliah
</Link>
<Link href="/visualisasi/tipekelulusan" className="flex items-center gap-2 px-3 py-2 text-sm hover:bg-accent hover:text-accent-foreground rounded-md transition-colors">
<Clock className="h-4 w-4" />
Tipe Kelulusan
</Link>
<Link href="/visualisasi/beasiswa" className="flex items-center gap-2 px-3 py-2 text-sm hover:bg-accent hover:text-accent-foreground rounded-md transition-colors">
<BookOpen className="h-4 w-4" />
Beasiswa
</Link>
<Link href="/visualisasi/berprestasi" className="flex items-center gap-2 px-3 py-2 text-sm hover:bg-accent hover:text-accent-foreground rounded-md transition-colors">
<Award className="h-4 w-4" />
Prestasi
</Link>
</div>
{/* Kelola Data - Only for Admin */}
{user.role_user === 'admin' && (
<div className="space-y-1">
<h4 className="text-xs font-medium text-muted-foreground px-3">Kelola Data</h4>
<Link href="/keloladata/mahasiswa" className="flex items-center gap-2 px-3 py-2 text-sm hover:bg-accent hover:text-accent-foreground rounded-md transition-colors">
<GraduationCap className="h-4 w-4" />
Mahasiswa
</Link>
<Link href="/keloladata/beasiswa" className="flex items-center gap-2 px-3 py-2 text-sm hover:bg-accent hover:text-accent-foreground rounded-md transition-colors">
<BookOpen className="h-4 w-4" />
Beasiswa
</Link>
<Link href="/keloladata/prestasi" className="flex items-center gap-2 px-3 py-2 text-sm hover:bg-accent hover:text-accent-foreground rounded-md transition-colors">
<Award className="h-4 w-4" />
Prestasi
</Link>
</div>
)}
<div className="pt-4 border-t">
<div className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground">
<User className="h-4 w-4" />
{user.role_user === 'ketuajurusan' ? 'Ketua Jurusan' : 'Admin'}
</div>
<button
onClick={onLogout}
className="flex items-center gap-2 px-3 py-2 text-sm hover:bg-accent hover:text-accent-foreground rounded-md transition-colors w-full text-left"
>
<LogOut className="h-4 w-4" />
Logout
</button>
</div>
</div>
) : (
<div className="space-y-2">
<h3 className="text-sm font-semibold text-muted-foreground">Login</h3>
<p className="text-sm text-muted-foreground px-3">
Silakan login untuk mengakses menu Visualisasi dan Kelola Data
</p>
</div>
)}
</div>
);
};
export default Navbar;