Files
dta_webapp/ditch-the-agent/src/components/base/MapSearchComponent.tsx
2025-08-16 12:57:07 -05:00

166 lines
4.8 KiB
TypeScript

import React, { useState } from 'react';
import {
APIProvider,
Map,
AdvancedMarker,
Pin,
InfoWindow,
useMap,
useMapsLibrary,
MapCameraChangedEvent,
} from '@vis.gl/react-google-maps';
import { Box, Typography, useTheme, Button } from '@mui/material';
import { useNavigate } from 'react-router-dom';
import { PropertiesAPI } from 'types';
import DrawingManager from '../sections/dashboard/Home/Profile/DrawingManager';
import { cloneSourceShallow } from 'echarts/types/src/data/Source.js';
// Custom Marker component
interface MapMarkerProps {
property: PropertiesAPI;
onMarkerClick: (propertyId: number) => void;
onMarkerHover: (property: PropertiesAPI) => void;
onMarkerUnhover: () => void;
isListItemSelected: boolean;
centerMapToMarker: (position: google.maps.LatLngLiteral) => void;
}
const MapMarker: React.FC<MapMarkerProps> = ({
property,
onMarkerClick,
onMarkerHover,
onMarkerUnhover,
isListItemSelected,
centerMapToMarker,
}) => {
const theme = useTheme();
const [infowindowOpen, setInfowindowOpen] = useState(false);
const position = { lat: Number(property.latitude)!, lng: Number(property.longitude)! };
const handleMarkerClick = (e: any) => {
//e.stopPropagation();
setInfowindowOpen(true);
centerMapToMarker(position);
};
return (
<AdvancedMarker
position={position}
onClick={handleMarkerClick}
onMouseOver={() => {
onMarkerHover(property);
}}
onMouseOut={() => {
onMarkerUnhover();
}}
// You can use a custom pin or a regular one
// We'll use the Pin component for a simple custom look
// The isListItemSelected state will be handled by the parent
>
<Pin
background={isListItemSelected ? theme.palette.primary.main : theme.palette.secondary.main}
borderColor={isListItemSelected ? theme.palette.primary.dark : theme.palette.secondary.dark}
glyphColor={'white'}
/>
{infowindowOpen && (
<InfoWindow position={position} onCloseClick={() => setInfowindowOpen(false)}>
<Box sx={{ p: 1, minWidth: 150 }}>
<Typography variant="body2" sx={{ fontWeight: 'bold' }}>
{property.address}
</Typography>
<Typography variant="caption" color="text.secondary">
{property.city}, {property.state}
</Typography>
<Button size="small" onClick={() => onMarkerClick(property.id)} sx={{ mt: 1 }}>
View Details
</Button>
</Box>
</InfoWindow>
)}
</AdvancedMarker>
);
};
// Main Map Component
interface MapProps {
center: google.maps.LatLngLiteral;
zoom: number;
properties: PropertiesAPI[];
selectedPropertyId: number | null;
onBoundsChanged: (bounds: any) => void;
onBoxDrawn: (bounds: any) => void;
onMarkerClick: (propertyId: number) => void;
onMarkerHover: (property: PropertiesAPI) => void;
onMarkerUnhover: () => void;
}
const MapSerachComponent: React.FC<MapProps> = ({
center,
zoom,
properties,
selectedPropertyId,
onBoundsChanged,
onBoxDrawn,
onMarkerClick,
onMarkerHover,
onMarkerUnhover,
}) => {
const navigate = useNavigate();
const [map, setMap] = useState<google.maps.Map | null>(null);
const onMapChange = (event: MapCameraChangedEvent) => {
const bounds = event.bounds;
onBoundsChanged({
ne: bounds.northEast,
sw: bounds.southWest,
});
};
const handleMarkerClick = (propertyId: number) => {
console.log('clicked a marker');
navigate(`/property/${propertyId}`);
onMarkerClick(propertyId);
};
const centerMapToMarker = (position: google.maps.LatLngLiteral) => {
map?.setCenter(position);
map?.setZoom(15);
};
console.log(properties);
return (
<Box sx={{ height: '70vh', width: '100%', position: 'relative' }}>
<APIProvider apiKey={'AIzaSyDJTApP1OoMbo7b1CPltPu8IObxe8UQt7w'}>
<Map
defaultCenter={center}
defaultZoom={zoom}
//onCameraChanged={onMapChange}
mapId={'MapSearchComponent'} // Replace with your Map ID from Google Cloud Console
onLoad={setMap}
disableDefaultUI={true}
>
{properties.map(
(property) =>
property.latitude &&
property.longitude && (
<MapMarker
key={property.id}
property={property}
onMarkerClick={handleMarkerClick}
onMarkerHover={onMarkerHover}
onMarkerUnhover={onMarkerUnhover}
isListItemSelected={selectedPropertyId === property.id}
centerMapToMarker={centerMapToMarker}
/>
),
)}
{/* <DrawingManager onBoxDrawn={onBoxDrawn} /> */}
</Map>
</APIProvider>
</Box>
);
};
export default MapSerachComponent;