mirror of
https://gitea.gofwd.group/sean/gunbuilder-next-tailwind.git
synced 2025-12-05 18:46:45 -05:00
fixed admin icon and added admin routing if logged in
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
import { useState, ReactNode } from 'react';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import {
|
||||
Dialog,
|
||||
DialogBackdrop,
|
||||
@@ -32,8 +33,8 @@ const navigation = [
|
||||
// { name: 'Settings', href: '/admin/settings', icon: Cog6ToothIcon }, // optional/future
|
||||
];
|
||||
const userNavigation = [
|
||||
{ name: 'Your profile', href: '#' },
|
||||
{ name: 'Sign out', href: '#' },
|
||||
{ name: 'Your profile', href: '/account/profile' },
|
||||
{ name: 'Sign out', href: '/api/auth/signout' },
|
||||
];
|
||||
|
||||
function classNames(...classes: string[]) {
|
||||
@@ -43,6 +44,40 @@ function classNames(...classes: string[]) {
|
||||
export default function AdminNavbar({ children }: { children: ReactNode }) {
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false);
|
||||
const pathname = usePathname();
|
||||
const { data: session } = useSession();
|
||||
|
||||
// Get user display name
|
||||
const getUserDisplayName = () => {
|
||||
if (!session?.user) return 'Admin User';
|
||||
|
||||
const user = session.user as any;
|
||||
if (user.first_name && user.last_name) {
|
||||
return `${user.first_name} ${user.last_name}`;
|
||||
}
|
||||
if (user.name) {
|
||||
return user.name;
|
||||
}
|
||||
if (user.email) {
|
||||
return user.email.split('@')[0]; // Use email prefix as fallback
|
||||
}
|
||||
return 'Admin User';
|
||||
};
|
||||
|
||||
const getUserInitials = () => {
|
||||
if (!session?.user) return 'A';
|
||||
|
||||
const user = session.user as any;
|
||||
if (user.first_name && user.last_name) {
|
||||
return `${user.first_name[0]}${user.last_name[0]}`.toUpperCase();
|
||||
}
|
||||
if (user.name) {
|
||||
return user.name.split(' ').map((n: string) => n[0]).join('').toUpperCase().slice(0, 2);
|
||||
}
|
||||
if (user.email) {
|
||||
return user.email[0].toUpperCase();
|
||||
}
|
||||
return 'A';
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -203,6 +238,15 @@ export default function AdminNavbar({ children }: { children: ReactNode }) {
|
||||
className="pointer-events-none col-start-1 row-start-1 size-5 self-center text-gray-400"
|
||||
/>
|
||||
</form>
|
||||
|
||||
{/* Back to Site Button */}
|
||||
<a
|
||||
href="/"
|
||||
className="inline-flex items-center px-3 py-2 text-sm font-medium text-gray-700 bg-gray-100 rounded-md hover:bg-gray-200 transition-colors"
|
||||
>
|
||||
<HomeIcon className="w-4 h-4 mr-2" />
|
||||
Back to Site
|
||||
</a>
|
||||
<div className="flex items-center gap-x-4 lg:gap-x-6">
|
||||
<button type="button" className="-m-2.5 p-2.5 text-gray-400 hover:text-gray-500">
|
||||
<span className="sr-only">View notifications</span>
|
||||
@@ -217,27 +261,32 @@ export default function AdminNavbar({ children }: { children: ReactNode }) {
|
||||
<MenuButton className="relative flex items-center">
|
||||
<span className="absolute -inset-1.5" />
|
||||
<span className="sr-only">Open user menu</span>
|
||||
<img
|
||||
alt=""
|
||||
src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80"
|
||||
className="size-8 rounded-full bg-gray-50"
|
||||
/>
|
||||
<div className="size-8 rounded-full bg-indigo-600 flex items-center justify-center">
|
||||
<span className="text-sm font-medium text-white">
|
||||
{getUserInitials()}
|
||||
</span>
|
||||
</div>
|
||||
<span className="hidden lg:flex lg:items-center">
|
||||
<span aria-hidden="true" className="ml-4 text-sm/6 font-semibold text-gray-900">
|
||||
Tom Cook
|
||||
{getUserDisplayName()}
|
||||
</span>
|
||||
<ChevronDownIcon aria-hidden="true" className="ml-2 size-5 text-gray-400" />
|
||||
</span>
|
||||
</MenuButton>
|
||||
<MenuItems
|
||||
transition
|
||||
className="absolute right-0 z-10 mt-2.5 w-32 origin-top-right rounded-md bg-white py-2 shadow-lg ring-1 ring-gray-900/5 transition focus:outline-none data-[closed]:scale-95 data-[closed]:transform data-[closed]:opacity-0 data-[enter]:duration-100 data-[leave]:duration-75 data-[enter]:ease-out data-[leave]:ease-in"
|
||||
className="absolute right-0 z-10 mt-2.5 w-48 origin-top-right rounded-md bg-white py-2 shadow-lg ring-1 ring-gray-900/5 transition focus:outline-none data-[closed]:scale-95 data-[closed]:transform data-[closed]:opacity-0 data-[enter]:duration-100 data-[leave]:duration-75 data-[enter]:ease-out data-[leave]:ease-in"
|
||||
>
|
||||
{session?.user && (
|
||||
<div className="px-3 py-2 text-xs text-gray-500 border-b border-gray-100">
|
||||
{session.user.email}
|
||||
</div>
|
||||
)}
|
||||
{userNavigation.map((item) => (
|
||||
<MenuItem key={item.name}>
|
||||
<a
|
||||
href={item.href}
|
||||
className="block px-3 py-1 text-sm/6 text-gray-900 data-[focus]:bg-gray-50 data-[focus]:outline-none"
|
||||
className="block px-3 py-2 text-sm text-gray-900 data-[focus]:bg-gray-50 data-[focus]:outline-none hover:bg-gray-50"
|
||||
>
|
||||
{item.name}
|
||||
</a>
|
||||
|
||||
11
src/app/admin/AdminProviders.tsx
Normal file
11
src/app/admin/AdminProviders.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
'use client';
|
||||
|
||||
import { SessionProvider } from 'next-auth/react';
|
||||
|
||||
export default function AdminProviders({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<SessionProvider>
|
||||
{children}
|
||||
</SessionProvider>
|
||||
);
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
import AdminNavbar from './AdminNavbar';
|
||||
import AdminProviders from './AdminProviders';
|
||||
|
||||
export default async function AdminLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<AdminNavbar>
|
||||
{children}
|
||||
</AdminNavbar>
|
||||
<AdminProviders>
|
||||
<AdminNavbar>
|
||||
{children}
|
||||
</AdminNavbar>
|
||||
</AdminProviders>
|
||||
);
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import ThemeSwitcher from './ThemeSwitcher';
|
||||
import { MagnifyingGlassIcon } from '@heroicons/react/24/outline';
|
||||
import { useSession, signIn, signOut } from 'next-auth/react';
|
||||
import { useState, ReactNode } from 'react';
|
||||
import { ShieldCheckIcon } from '@heroicons/react/24/outline';
|
||||
|
||||
interface MenuItem {
|
||||
label: string;
|
||||
@@ -37,6 +38,14 @@ export default function Navbar() {
|
||||
onClick: () => setMenuOpen(false),
|
||||
}
|
||||
: undefined,
|
||||
// Admin link for admin users
|
||||
session?.user && (session.user as any)?.isAdmin
|
||||
? {
|
||||
label: 'Admin Dashboard',
|
||||
href: '/admin',
|
||||
onClick: () => setMenuOpen(false),
|
||||
}
|
||||
: undefined,
|
||||
session?.user
|
||||
? {
|
||||
label: 'Sign Out',
|
||||
@@ -64,6 +73,24 @@ export default function Navbar() {
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Admin Banner - Moved to top */}
|
||||
{session?.user && (session.user as any)?.isAdmin && (
|
||||
<div className="w-full bg-gradient-to-r from-purple-600 to-indigo-600 text-white py-2 px-4 sm:px-8 relative z-30">
|
||||
<div className="max-w-7xl mx-auto flex items-center justify-between">
|
||||
<div className="flex items-center space-x-2">
|
||||
<ShieldCheckIcon className="h-4 w-4" />
|
||||
<span className="text-sm font-medium">Admin Panel</span>
|
||||
</div>
|
||||
<Link
|
||||
href="/admin"
|
||||
className="text-sm hover:text-purple-200 transition-colors underline underline-offset-2"
|
||||
>
|
||||
Go to Admin Dashboard →
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Top Bar */}
|
||||
<div className="w-full bg-[#4B6516] text-white h-10 flex items-center justify-between px-4 sm:px-8 relative z-20">
|
||||
<Link href="/" className="font-bold text-lg tracking-tight hover:underline focus:underline">Pew Builder</Link>
|
||||
|
||||
Reference in New Issue
Block a user