2026-02-07 00:34:47 +00:00
|
|
|
import type { AuthUser } from '@/auth/types';
|
2026-02-09 21:31:45 +00:00
|
|
|
import type { TaskState } from '@/types';
|
2026-02-01 17:28:37 +00:00
|
|
|
import { Button } from './ui/button';
|
|
|
|
|
import { Separator } from './ui/separator';
|
2026-02-28 16:16:03 +00:00
|
|
|
import { Tabs, TabsList, TabsTrigger } from './ui/tabs';
|
2026-02-21 11:34:53 +00:00
|
|
|
import { LogOut, Home } from 'lucide-react';
|
2026-02-01 17:28:37 +00:00
|
|
|
import { logout } from '@/auth/authService';
|
2026-02-07 00:34:47 +00:00
|
|
|
import { clearPasskeyUser } from '@/auth/passkeyService';
|
2026-02-01 17:28:37 +00:00
|
|
|
import { HealthIndicator } from './HealthIndicator';
|
|
|
|
|
import { TaskIndicator } from './TaskIndicator';
|
2026-02-21 11:34:53 +00:00
|
|
|
import { MobileMenu } from './MobileMenu';
|
|
|
|
|
import { useIsMobile } from '@/hooks/use-mobile';
|
2026-02-28 16:16:03 +00:00
|
|
|
import { ListingType } from './FilterPanel';
|
2026-02-01 17:28:37 +00:00
|
|
|
|
|
|
|
|
interface HeaderProps {
|
2026-02-07 00:34:47 +00:00
|
|
|
user: AuthUser;
|
2026-02-01 17:28:37 +00:00
|
|
|
activeFilterCount?: number;
|
|
|
|
|
isLoading?: boolean;
|
|
|
|
|
onToggleFilters?: () => void;
|
|
|
|
|
showFilterToggle?: boolean;
|
2026-02-09 23:02:24 +00:00
|
|
|
// Task progress (unified)
|
|
|
|
|
tasks: Record<string, TaskState>;
|
|
|
|
|
activeTaskId: string | null;
|
|
|
|
|
isConnected: boolean;
|
|
|
|
|
onCancelTask: (taskId: string) => Promise<boolean>;
|
|
|
|
|
onClearAllTasks: () => Promise<boolean>;
|
2026-02-08 15:11:21 +00:00
|
|
|
onTaskCompleted?: () => void;
|
2026-02-28 16:16:03 +00:00
|
|
|
// Listing type toggle
|
|
|
|
|
listingType?: ListingType;
|
|
|
|
|
onListingTypeChange?: (type: ListingType) => void;
|
2026-02-01 17:28:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function Header({
|
|
|
|
|
user,
|
2026-02-09 23:02:24 +00:00
|
|
|
tasks,
|
|
|
|
|
activeTaskId,
|
|
|
|
|
isConnected,
|
|
|
|
|
onCancelTask,
|
|
|
|
|
onClearAllTasks,
|
2026-02-08 15:11:21 +00:00
|
|
|
onTaskCompleted,
|
2026-02-28 16:16:03 +00:00
|
|
|
listingType,
|
|
|
|
|
onListingTypeChange,
|
2026-02-01 17:28:37 +00:00
|
|
|
}: HeaderProps) {
|
2026-02-21 11:34:53 +00:00
|
|
|
const isMobile = useIsMobile();
|
|
|
|
|
|
2026-02-07 00:34:47 +00:00
|
|
|
const handleLogout = async () => {
|
|
|
|
|
if (user.provider === 'passkey') {
|
|
|
|
|
clearPasskeyUser();
|
|
|
|
|
window.location.reload();
|
|
|
|
|
} else {
|
|
|
|
|
await logout();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2026-02-01 17:28:37 +00:00
|
|
|
return (
|
2026-02-21 11:34:53 +00:00
|
|
|
<header className={`flex shrink-0 items-center gap-3 border-b bg-background px-4 ${isMobile ? 'h-12' : 'h-14'}`}>
|
2026-02-01 17:28:37 +00:00
|
|
|
{/* 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>
|
|
|
|
|
|
2026-02-28 16:16:03 +00:00
|
|
|
{/* 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>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
|
2026-02-21 11:34:53 +00:00
|
|
|
{/* Desktop-only items */}
|
|
|
|
|
{!isMobile && (
|
|
|
|
|
<>
|
|
|
|
|
<Separator orientation="vertical" className="h-6" />
|
|
|
|
|
<HealthIndicator />
|
|
|
|
|
<TaskIndicator
|
|
|
|
|
tasks={tasks}
|
|
|
|
|
activeTaskId={activeTaskId}
|
|
|
|
|
isConnected={isConnected}
|
|
|
|
|
onCancelTask={onCancelTask}
|
|
|
|
|
onClearAllTasks={onClearAllTasks}
|
|
|
|
|
onTaskCompleted={onTaskCompleted}
|
|
|
|
|
/>
|
|
|
|
|
</>
|
2026-02-01 17:28:37 +00:00
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{/* Spacer */}
|
|
|
|
|
<div className="flex-1" />
|
|
|
|
|
|
2026-02-21 11:34:53 +00:00
|
|
|
{/* 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>
|
|
|
|
|
)}
|
2026-02-01 17:28:37 +00:00
|
|
|
</header>
|
|
|
|
|
);
|
|
|
|
|
}
|