146 lines
4.9 KiB
TypeScript
146 lines
4.9 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import Link from 'next/link';
|
|
import Image from 'next/image';
|
|
import { Geist, Geist_Mono } from "next/font/google";
|
|
import "../../globals.css";
|
|
import DatabaseInitializer from "@/lib/components/DatabaseInitializer";
|
|
import UserMenu from "@/lib/components/UserMenu";
|
|
import ThemeToggle from "@/lib/components/ThemeToggle";
|
|
import { ThemeProvider } from "@/lib/context/ThemeContext";
|
|
|
|
const geistSans = Geist({
|
|
variable: "--font-geist-sans",
|
|
subsets: ["latin"],
|
|
});
|
|
|
|
const geistMono = Geist_Mono({
|
|
variable: "--font-geist-mono",
|
|
subsets: ["latin"],
|
|
});
|
|
|
|
interface User {
|
|
id: string;
|
|
username: string;
|
|
avatar: string | null;
|
|
}
|
|
|
|
export default function RootLayout({
|
|
children,
|
|
}: Readonly<{
|
|
children: React.ReactNode;
|
|
}>) {
|
|
const [user, setUser] = useState<User | null>(null);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const fetchUser = async () => {
|
|
try {
|
|
const response = await fetch('/api/auth');
|
|
const data = await response.json();
|
|
|
|
if (data.authenticated) {
|
|
setUser(data.user);
|
|
}
|
|
} catch (error) {
|
|
console.error('Error fetching user:', error);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
|
|
fetchUser();
|
|
}, []);
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<html><body>
|
|
<div className="min-h-screen flex items-center justify-center bg-gray-100">
|
|
<div className="text-center">
|
|
<p className="text-gray-500">Loading...</p>
|
|
</div>
|
|
</div>
|
|
</body></html>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<html lang="en">
|
|
<body
|
|
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
>
|
|
<ThemeProvider>
|
|
<div className="min-h-screen bg-gray-100">
|
|
<nav className="bg-white shadow-sm">
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="flex justify-between h-16">
|
|
<div className="flex">
|
|
<div className="flex-shrink-0 flex items-center">
|
|
<Link href="/admin" className="text-xl font-bold text-gray-800">
|
|
KantanCMS Admin
|
|
</Link>
|
|
</div>
|
|
<div className="hidden sm:ml-6 sm:flex sm:space-x-8">
|
|
<Link
|
|
href="/admin"
|
|
className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
|
|
>
|
|
Dashboard
|
|
</Link>
|
|
<Link
|
|
href="/admin/posts"
|
|
className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
|
|
>
|
|
Posts
|
|
</Link>
|
|
<Link
|
|
href="/admin/users"
|
|
className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
|
|
>
|
|
Users
|
|
</Link>
|
|
<Link
|
|
href="/admin/customers"
|
|
className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
|
|
>
|
|
Customers
|
|
</Link>
|
|
<Link
|
|
href="/admin/contact-records"
|
|
className="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium"
|
|
>
|
|
Contact Records
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
<div className="hidden sm:ml-6 sm:flex sm:items-center">
|
|
<ThemeToggle className="mr-4" />
|
|
{user && (
|
|
<UserMenu user={user} isAdmin={true} />
|
|
)}
|
|
<Link
|
|
href="/"
|
|
className="text-gray-500 hover:text-gray-700 px-3 py-2 rounded-md text-sm font-medium ml-4"
|
|
>
|
|
View Site
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div className="py-10">
|
|
<main>
|
|
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
|
<div className="px-4 py-8 sm:px-0">{children}</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
</ThemeProvider>
|
|
</body></html>
|
|
|
|
);
|
|
}
|