feat: integrate FilterBar into layout, remove sidebar

Replace the fixed w-80 sidebar with a horizontal FilterBar below the
header, giving the map full viewport width. Key changes:

- App.tsx: Remove sidebar layout, add FilterBar + FilterChips + inline
  StreamingProgressBar between header and main content area
- Header.tsx: Add Rent/Buy listing type toggle (compact Tabs) after logo
- StatsBar.tsx: Add "Color by" metric selector (moved from
  VisualizationCard) as a compact Select alongside view mode toggles
- Mobile: Replace Sheet-based filter panel with full-screen Dialog
This commit is contained in:
Viktor Barzin 2026-02-28 16:16:03 +00:00
parent 4053c0c759
commit 8f112f30e3
No known key found for this signature in database
GPG key ID: 0EB088298288D958
3 changed files with 235 additions and 122 deletions

View file

@ -2,6 +2,7 @@ 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';
@ -9,6 +10,7 @@ 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;
@ -23,6 +25,9 @@ interface HeaderProps {
onCancelTask: (taskId: string) => Promise<boolean>;
onClearAllTasks: () => Promise<boolean>;
onTaskCompleted?: () => void;
// Listing type toggle
listingType?: ListingType;
onListingTypeChange?: (type: ListingType) => void;
}
export function Header({
@ -33,6 +38,8 @@ export function Header({
onCancelTask,
onClearAllTasks,
onTaskCompleted,
listingType,
onListingTypeChange,
}: HeaderProps) {
const isMobile = useIsMobile();
@ -53,6 +60,26 @@ export function Header({
<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 && (
<>