miniperplx/components/nearby-search-map-view.tsx

146 lines
4.2 KiB
TypeScript

/* eslint-disable @next/next/no-img-element */
import React, { useState } from 'react';
import { cn } from "@/lib/utils";
import dynamic from 'next/dynamic';
import PlaceCard from './place-card';
import { Badge } from './ui/badge';
interface Location {
lat: number;
lng: number;
}
interface Photo {
thumbnail: string;
small: string;
medium: string;
large: string;
original: string;
caption?: string;
}
interface Place {
name: string;
location: Location;
place_id: string;
vicinity: string;
rating?: number;
reviews_count?: number;
price_level?: string;
description?: string;
photos?: Photo[];
is_closed?: boolean;
next_open_close?: string;
type?: string;
cuisine?: string;
source?: string;
phone?: string;
website?: string;
hours?: string[];
distance?: string;
bearing?: string;
}
// Dynamic import for the map component
const InteractiveMap = dynamic(() => import('./interactive-maps'), { ssr: false });
interface NearbySearchMapViewProps {
center: {
lat: number;
lng: number;
};
places: Place[];
type: string;
}
const NearbySearchMapView: React.FC<NearbySearchMapViewProps> = ({
center,
places,
type,
}) => {
const [viewMode, setViewMode] = useState<'map' | 'list'>('map');
const [selectedPlace, setSelectedPlace] = useState<Place | null>(null);
return (
<div className="relative w-full h-[70vh] bg-white dark:bg-neutral-900 rounded-lg overflow-hidden border border-neutral-200 dark:border-neutral-800">
<Badge variant={"secondary"} className="absolute top-4 left-4 z-10">Beta</Badge>
{/* View Toggle */}
<div className="absolute top-4 right-4 z-10 flex rounded-full bg-white dark:bg-black border border-neutral-200 dark:border-neutral-700 p-0.5 shadow-lg">
<button
onClick={() => setViewMode('list')}
className={cn(
"px-4 py-1 rounded-full text-sm font-medium transition-colors",
viewMode === 'list'
? "bg-black dark:bg-white text-white dark:text-black"
: "text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-white"
)}
>
List
</button>
<button
onClick={() => setViewMode('map')}
className={cn(
"px-4 py-1 rounded-full text-sm font-medium transition-colors",
viewMode === 'map'
? "bg-black dark:bg-white text-white dark:text-black"
: "text-neutral-600 dark:text-neutral-400 hover:text-neutral-900 dark:hover:text-white"
)}
>
Map
</button>
</div>
<div className={cn(
"w-full h-full flex flex-col",
viewMode === 'list' ? 'divide-y divide-neutral-200 dark:divide-neutral-800' : ''
)}>
{/* Map Container */}
<div className={cn(
"w-full transition-all duration-300",
viewMode === 'map' ? 'h-full' : 'h-[40%]'
)}>
<InteractiveMap
center={center}
places={places}
selectedPlace={selectedPlace}
onPlaceSelect={setSelectedPlace}
/>
{/* Selected Place Overlay - Only show in map view */}
{selectedPlace && viewMode === 'map' && (
<div className="absolute left-4 right-4 bottom-4 z-10">
<PlaceCard
place={selectedPlace}
onClick={() => {}}
isSelected={true}
variant="overlay"
/>
</div>
)}
</div>
{/* List Container */}
{viewMode === 'list' && (
<div className="h-[60%] bg-white dark:bg-neutral-900">
<div className="h-full overflow-y-auto">
<div className="max-w-3xl mx-auto p-4 space-y-4">
{places.map((place, index) => (
<PlaceCard
key={index}
place={place}
onClick={() => setSelectedPlace(place)}
isSelected={selectedPlace?.place_id === place.place_id}
variant="list"
/>
))}
</div>
</div>
</div>
)}
</div>
</div>
);
};
export default NearbySearchMapView;