Tanya de2144be2a feat: Add new scripts and update project structure for database management and user authentication
This commit introduces several new scripts for managing database operations, including user creation, permission grants, and data migrations. It also adds new documentation files to guide users through the setup and configuration processes. Additionally, the project structure is updated to enhance organization and maintainability, ensuring a smoother development experience for contributors. These changes support the ongoing transition to a web-based architecture and improve overall project functionality.
2026-01-06 13:53:24 -05:00

192 lines
6.8 KiB
TypeScript

'use client';
import { useState } from 'react';
import { useSession, signOut } from 'next-auth/react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { User, LogIn, UserPlus, Users, Home, Upload } from 'lucide-react';
import { Button } from '@/components/ui/button';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/tooltip';
import { LoginDialog } from '@/components/LoginDialog';
import { RegisterDialog } from '@/components/RegisterDialog';
import { ManageUsersPageClient } from '@/app/admin/users/ManageUsersPageClient';
export function Header() {
const { data: session, status } = useSession();
const router = useRouter();
const [loginDialogOpen, setLoginDialogOpen] = useState(false);
const [registerDialogOpen, setRegisterDialogOpen] = useState(false);
const [manageUsersOpen, setManageUsersOpen] = useState(false);
const [popoverOpen, setPopoverOpen] = useState(false);
const handleSignOut = async () => {
await signOut({ callbackUrl: '/' });
};
return (
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="w-full flex h-16 items-center justify-between px-4">
<div className="flex items-center space-x-3">
{/* Home button - commented out for future use */}
{/* <Tooltip>
<TooltipTrigger asChild>
<Button
variant="default"
size="icon"
asChild
className="bg-primary hover:bg-primary/90 rounded-lg"
>
<Link href="/" aria-label="Home">
<Home className="h-5 w-5" />
</Link>
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Go to Home</p>
</TooltipContent>
</Tooltip> */}
</div>
<div className="flex items-center gap-2">
{session?.user && (
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
asChild
className="bg-blue-100 hover:bg-blue-200 dark:bg-blue-900 dark:hover:bg-blue-800"
>
<Link href="/upload" aria-label="Upload Photos">
<Upload className="h-5 w-5" />
</Link>
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Upload your own photos</p>
</TooltipContent>
</Tooltip>
)}
{status === 'loading' ? (
<div className="h-9 w-9 animate-pulse rounded-full bg-gray-200 dark:bg-gray-700" />
) : session?.user ? (
<Popover open={popoverOpen} onOpenChange={setPopoverOpen}>
<PopoverTrigger asChild>
<Button
variant="ghost"
size="icon"
className="h-9 w-9 rounded-full"
aria-label="Account menu"
>
<User className="h-5 w-5 text-orange-600" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-56 p-2" align="end">
<div className="space-y-1">
<div className="px-2 py-1.5">
<p className="text-sm font-medium text-secondary">
{session.user.name || 'User'}
</p>
<p className="text-xs text-muted-foreground">
{session.user.email}
</p>
</div>
<div className="border-t pt-1">
<Button
variant="ghost"
className="w-full justify-start text-sm text-secondary hover:text-secondary hover:bg-secondary/10"
onClick={() => {
setPopoverOpen(false);
router.push('/upload');
}}
>
<Upload className="mr-2 h-4 w-4" />
Upload Photos
</Button>
{session.user.isAdmin && (
<Button
variant="ghost"
className="w-full justify-start text-sm text-secondary hover:text-secondary hover:bg-secondary/10"
onClick={() => {
setPopoverOpen(false);
setManageUsersOpen(true);
}}
>
<Users className="mr-2 h-4 w-4" />
Manage Users
</Button>
)}
<Button
variant="ghost"
className="w-full justify-start text-sm text-secondary hover:text-secondary hover:bg-secondary/10"
onClick={() => {
setPopoverOpen(false);
handleSignOut();
}}
>
Sign out
</Button>
</div>
</div>
</PopoverContent>
</Popover>
) : (
<div className="flex items-center gap-2">
<Button
variant="ghost"
size="sm"
onClick={() => setLoginDialogOpen(true)}
className="flex items-center gap-2"
>
<LogIn className="h-4 w-4" />
<span className="hidden sm:inline">Sign in</span>
</Button>
<Button
size="sm"
onClick={() => setRegisterDialogOpen(true)}
className="flex items-center gap-2"
>
<UserPlus className="h-4 w-4" />
<span className="hidden sm:inline">Sign up</span>
</Button>
</div>
)}
</div>
</div>
<LoginDialog
open={loginDialogOpen}
onOpenChange={(open) => {
setLoginDialogOpen(open);
}}
onOpenRegister={() => {
setLoginDialogOpen(false);
setRegisterDialogOpen(true);
}}
/>
<RegisterDialog
open={registerDialogOpen}
onOpenChange={(open) => {
setRegisterDialogOpen(open);
}}
onOpenLogin={() => {
setRegisterDialogOpen(false);
setLoginDialogOpen(true);
}}
/>
{manageUsersOpen && (
<ManageUsersPageClient onClose={() => setManageUsersOpen(false)} />
)}
</header>
);
}