Files
storycove/frontend/src/components/layout/Header.tsx
2025-08-08 14:09:14 +02:00

208 lines
6.8 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import { useState } from 'react';
import Link from 'next/link';
import Image from 'next/image';
import { useRouter } from 'next/navigation';
import { useAuth } from '../../contexts/AuthContext';
import { useTheme } from '../../lib/theme';
import Button from '../ui/Button';
import Dropdown from '../ui/Dropdown';
export default function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const { logout } = useAuth();
const { theme, toggleTheme } = useTheme();
const router = useRouter();
const addStoryItems = [
{
href: '/add-story',
label: 'Manual Entry',
description: 'Add a story by manually entering details'
},
{
href: '/stories/import',
label: 'Import from URL',
description: 'Import a single story from a website'
},
{
href: '/stories/import/epub',
label: 'Import EPUB',
description: 'Import a story from an EPUB file'
},
{
href: '/stories/import/bulk',
label: 'Bulk Import',
description: 'Import multiple stories from a list of URLs'
}
];
const handleLogout = () => {
logout();
router.push('/login');
};
return (
<header className="theme-card theme-shadow border-b theme-border sticky top-0 z-50">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
{/* Logo and Brand */}
<Link href="/library" className="flex items-center space-x-3">
<Image
src={theme === 'dark' ? '/logo-dark-medium.png' : '/logo-medium.png'}
alt="StoryCove"
width={40}
height={40}
priority
/>
<span className="text-xl font-bold theme-header hidden sm:block">
StoryCove
</span>
</Link>
{/* Desktop Navigation */}
<nav className="hidden md:flex items-center space-x-6">
<Link
href="/library"
className="theme-text hover:theme-accent transition-colors font-medium"
>
Library
</Link>
<Link
href="/collections"
className="theme-text hover:theme-accent transition-colors font-medium"
>
Collections
</Link>
<Link
href="/authors"
className="theme-text hover:theme-accent transition-colors font-medium"
>
Authors
</Link>
<Dropdown
trigger="Add Story"
items={addStoryItems}
/>
</nav>
{/* Right side actions */}
<div className="flex items-center space-x-4">
{/* Theme Toggle */}
<button
onClick={toggleTheme}
className="p-2 rounded-lg theme-text hover:theme-accent transition-colors"
aria-label="Toggle theme"
>
{theme === 'light' ? '🌙' : '☀️'}
</button>
{/* Settings */}
<Link
href="/settings"
className="p-2 rounded-lg theme-text hover:theme-accent transition-colors"
aria-label="Settings"
>
</Link>
{/* Logout */}
<Button
variant="ghost"
size="sm"
onClick={handleLogout}
className="hidden md:inline-flex"
>
Logout
</Button>
{/* Mobile menu button */}
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="md:hidden p-2 rounded-lg theme-text hover:theme-accent transition-colors"
aria-label="Toggle menu"
>
{isMenuOpen ? '✕' : '☰'}
</button>
</div>
</div>
{/* Mobile Navigation */}
{isMenuOpen && (
<div className="md:hidden border-t theme-border py-4">
<div className="flex flex-col space-y-3">
<Link
href="/library"
className="theme-text hover:theme-accent transition-colors font-medium px-2 py-1"
onClick={() => setIsMenuOpen(false)}
>
Library
</Link>
<Link
href="/collections"
className="theme-text hover:theme-accent transition-colors font-medium px-2 py-1"
onClick={() => setIsMenuOpen(false)}
>
Collections
</Link>
<Link
href="/authors"
className="theme-text hover:theme-accent transition-colors font-medium px-2 py-1"
onClick={() => setIsMenuOpen(false)}
>
Authors
</Link>
<div className="px-2 py-1">
<div className="font-medium theme-text mb-1">Add Story</div>
<div className="pl-4 space-y-1">
<Link
href="/add-story"
className="block theme-text hover:theme-accent transition-colors text-sm py-1"
onClick={() => setIsMenuOpen(false)}
>
Manual Entry
</Link>
<Link
href="/stories/import"
className="block theme-text hover:theme-accent transition-colors text-sm py-1"
onClick={() => setIsMenuOpen(false)}
>
Import from URL
</Link>
<Link
href="/stories/import/epub"
className="block theme-text hover:theme-accent transition-colors text-sm py-1"
onClick={() => setIsMenuOpen(false)}
>
Import EPUB
</Link>
<Link
href="/stories/import/bulk"
className="block theme-text hover:theme-accent transition-colors text-sm py-1"
onClick={() => setIsMenuOpen(false)}
>
Bulk Import
</Link>
</div>
</div>
<Link
href="/settings"
className="theme-text hover:theme-accent transition-colors font-medium px-2 py-1"
onClick={() => setIsMenuOpen(false)}
>
Settings
</Link>
<button
onClick={handleLogout}
className="theme-text hover:theme-accent transition-colors font-medium px-2 py-1 text-left"
>
Logout
</button>
</div>
</div>
)}
</div>
</header>
);
}