All checks were successful
Deploy to Web Server flyer-crawler.projectium.com / deploy (push) Successful in 3m21s
140 lines
6.1 KiB
TypeScript
140 lines
6.1 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { ShoppingCartIcon } from './icons/ShoppingCartIcon';
|
|
import { DarkModeToggle } from './DarkModeToggle';
|
|
import { UnitSystemToggle } from './UnitSystemToggle';
|
|
import { Session } from '@supabase/supabase-js';
|
|
import { supabase } from '../services/supabaseClient';
|
|
import { AuthModal } from './AuthModal';
|
|
import { SignUpModal } from './SignUpModal';
|
|
import { UserIcon } from './icons/UserIcon';
|
|
import { Cog8ToothIcon } from './icons/Cog8ToothIcon';
|
|
import { MicrophoneIcon } from './icons/MicrophoneIcon';
|
|
import { Link } from 'react-router-dom';
|
|
import { ShieldCheckIcon } from './icons/ShieldCheckIcon';
|
|
import { Profile } from '../types';
|
|
|
|
type AuthStatus = 'SIGNED_OUT' | 'ANONYMOUS' | 'AUTHENTICATED';
|
|
interface HeaderProps {
|
|
isDarkMode: boolean;
|
|
toggleDarkMode: () => void;
|
|
unitSystem: 'metric' | 'imperial';
|
|
toggleUnitSystem: () => void;
|
|
session: Session | null;
|
|
authStatus: AuthStatus;
|
|
profile: Profile | null;
|
|
onOpenProfile: () => void;
|
|
onOpenVoiceAssistant: () => void;
|
|
onSignOut: () => void;
|
|
}
|
|
|
|
export const Header: React.FC<HeaderProps> = ({ isDarkMode, toggleDarkMode, unitSystem, toggleUnitSystem, session, authStatus, profile, onOpenProfile, onOpenVoiceAssistant, onSignOut }) => {
|
|
const [isSignInModalOpen, setIsSignInModalOpen] = useState(false);
|
|
const [isSignUpModalOpen, setIsSignUpModalOpen] = useState(false);
|
|
|
|
const openSignIn = () => {
|
|
setIsSignUpModalOpen(false);
|
|
setIsSignInModalOpen(true);
|
|
};
|
|
|
|
const openSignUp = () => {
|
|
setIsSignInModalOpen(false);
|
|
setIsSignUpModalOpen(true);
|
|
};
|
|
|
|
|
|
return (
|
|
<>
|
|
<header className="bg-white dark:bg-gray-900 shadow-md sticky top-0 z-20">
|
|
<div className="max-w-screen-2xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div className="flex items-center justify-between h-16">
|
|
<div className="flex items-center">
|
|
<ShoppingCartIcon className="h-8 w-8 text-brand-primary" />
|
|
<h1 className="ml-3 text-2xl font-bold text-gray-800 dark:text-white">
|
|
Flyer Crawler
|
|
</h1>
|
|
</div>
|
|
<div className="flex items-center space-x-4 md:space-x-6">
|
|
{session && (
|
|
<button
|
|
onClick={onOpenVoiceAssistant}
|
|
className="p-1.5 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700/50 text-gray-500 dark:text-gray-400 transition-colors"
|
|
aria-label="Open voice assistant"
|
|
title="Voice Assistant"
|
|
>
|
|
<MicrophoneIcon className="w-5 h-5" />
|
|
</button>
|
|
)}
|
|
<UnitSystemToggle currentSystem={unitSystem} onToggle={toggleUnitSystem} />
|
|
<DarkModeToggle isDarkMode={isDarkMode} onToggle={toggleDarkMode} />
|
|
<div className="w-px h-6 bg-gray-200 dark:bg-gray-700 hidden sm:block"></div>
|
|
{session ? (
|
|
<div className="flex items-center space-x-3">
|
|
<div className="hidden md:flex items-center space-x-2 text-sm">
|
|
<UserIcon className="w-5 h-5 text-gray-500 dark:text-gray-400" />
|
|
{authStatus === 'AUTHENTICATED' ? (
|
|
<span className="font-medium text-gray-700 dark:text-gray-300">{session.user.email}</span>
|
|
) : (
|
|
<span className="font-medium text-gray-500 dark:text-gray-400 italic">Guest</span>
|
|
)}
|
|
</div>
|
|
<button
|
|
onClick={onOpenProfile}
|
|
className="p-1.5 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700/50 text-gray-500 dark:text-gray-400 transition-colors"
|
|
aria-label="Open my account settings"
|
|
title="My Account"
|
|
>
|
|
<Cog8ToothIcon className="w-5 h-5" />
|
|
</button>
|
|
{profile?.role === 'admin' && (
|
|
<Link to="/admin" className="p-1.5 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700/50 text-gray-500 dark:text-gray-400 transition-colors" title="Admin Area">
|
|
<ShieldCheckIcon className="w-5 h-5" />
|
|
</Link>
|
|
)}
|
|
<button
|
|
onClick={onOpenProfile}
|
|
className="p-1.5 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700/50 text-gray-500 dark:text-gray-400 transition-colors"
|
|
aria-label="Open my account settings"
|
|
title="My Account"
|
|
>
|
|
<Cog8ToothIcon className="w-5 h-5" />
|
|
</button>
|
|
<button
|
|
onClick={onSignOut}
|
|
className="text-sm font-semibold text-gray-600 hover:text-brand-primary dark:text-gray-300 dark:hover:text-brand-light transition-colors"
|
|
>
|
|
Logout
|
|
</button>
|
|
</div>
|
|
) : (
|
|
<div className="flex items-center space-x-2">
|
|
<button
|
|
onClick={openSignIn}
|
|
className="text-sm font-semibold text-gray-600 hover:text-brand-primary dark:text-gray-300 dark:hover:text-brand-light transition-colors"
|
|
>
|
|
Login
|
|
</button>
|
|
<button
|
|
onClick={openSignUp}
|
|
className="px-3 py-1.5 text-sm font-semibold text-white bg-brand-primary hover:bg-brand-secondary rounded-md transition-colors"
|
|
>
|
|
Sign Up
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
{isSignInModalOpen && supabase && (
|
|
<AuthModal
|
|
isOpen={isSignInModalOpen}
|
|
onClose={() => setIsSignInModalOpen(false)}
|
|
onSwitchToSignUp={openSignUp}
|
|
/>
|
|
)}
|
|
{isSignUpModalOpen && supabase && (
|
|
<SignUpModal isOpen={isSignUpModalOpen} onClose={() => setIsSignUpModalOpen(false)} onSwitchToSignIn={openSignIn} />
|
|
)}
|
|
</>
|
|
);
|
|
}; |