wrongmove/frontend/src/components/Header.tsx

135 lines
4.6 KiB
TypeScript
Raw Normal View History

import type { AuthUser } from '@/auth/types';
import type { TaskState } from '@/types';
import { Button } from './ui/button';
import { Separator } from './ui/separator';
import { Tabs, TabsList, TabsTrigger } from './ui/tabs';
import { LogOut, Home } from 'lucide-react';
import { logout } from '@/auth/authService';
import { clearPasskeyUser } from '@/auth/passkeyService';
import { HealthIndicator } from './HealthIndicator';
import { TaskIndicator } from './TaskIndicator';
import { MobileMenu } from './MobileMenu';
import { useIsMobile } from '@/hooks/use-mobile';
import { ListingType } from './FilterPanel';
interface HeaderProps {
user: AuthUser;
activeFilterCount?: number;
isLoading?: boolean;
onToggleFilters?: () => void;
showFilterToggle?: boolean;
// Task progress (unified)
tasks: Record<string, TaskState>;
activeTaskId: string | null;
isConnected: boolean;
onCancelTask: (taskId: string) => Promise<boolean>;
onClearAllTasks: () => Promise<boolean>;
onTaskCompleted?: () => void;
// Listing type toggle
listingType?: ListingType;
onListingTypeChange?: (type: ListingType) => void;
}
export function Header({
user,
tasks,
activeTaskId,
isConnected,
onCancelTask,
onClearAllTasks,
onTaskCompleted,
listingType,
onListingTypeChange,
}: HeaderProps) {
const isMobile = useIsMobile();
const handleLogout = async () => {
if (user.provider === 'passkey') {
clearPasskeyUser();
window.location.reload();
} else {
await logout();
}
};
return (
<header className={`flex shrink-0 items-center gap-3 border-b bg-background px-4 ${isMobile ? 'h-12' : 'h-14'}`}>
{/* Logo / Brand */}
<div className="flex items-center gap-2">
<Home className="h-5 w-5 text-primary" />
<span className="font-semibold text-lg hidden sm:inline">Wrongmove</span>
</div>
{/* Listing Type Toggle (Rent / Buy) */}
{listingType && onListingTypeChange && (
<>
<Separator orientation="vertical" className="h-6" />
<Tabs
value={listingType}
onValueChange={(v) => onListingTypeChange(v as ListingType)}
>
<TabsList className="h-8 w-auto p-0.5">
<TabsTrigger value={ListingType.RENT} className="h-7 px-3 text-xs flex-initial">
Rent
</TabsTrigger>
<TabsTrigger value={ListingType.BUY} className="h-7 px-3 text-xs flex-initial">
Buy
</TabsTrigger>
</TabsList>
</Tabs>
</>
)}
{/* Desktop-only items */}
{!isMobile && (
<>
<Separator orientation="vertical" className="h-6" />
<HealthIndicator />
<TaskIndicator
tasks={tasks}
activeTaskId={activeTaskId}
isConnected={isConnected}
onCancelTask={onCancelTask}
onClearAllTasks={onClearAllTasks}
onTaskCompleted={onTaskCompleted}
/>
</>
)}
{/* Spacer */}
<div className="flex-1" />
{/* Mobile: hamburger menu */}
{isMobile && (
<MobileMenu
user={user}
tasks={tasks}
activeTaskId={activeTaskId}
isConnected={isConnected}
onCancelTask={onCancelTask}
onClearAllTasks={onClearAllTasks}
onTaskCompleted={onTaskCompleted}
/>
)}
{/* Desktop: user menu */}
{!isMobile && (
<div className="flex items-center gap-3">
<span className="text-sm text-muted-foreground">
{user.email}
</span>
<Button
variant="ghost"
size="sm"
onClick={handleLogout}
className="gap-2"
>
<LogOut className="h-4 w-4" />
Logout
</Button>
</div>
)}
</header>
);
}