"use client" import { useEffect, useRef, useState } from "react" import L from "leaflet" import { Badge } from "@/components/ui/badge" // Fix for default markers in Leaflet import "leaflet/dist/leaflet.css" // Available tile providers (no API keys required) const tileProviders = { osm: { name: "OpenStreetMap", url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", attribution: '© OpenStreetMap contributors' }, carto: { name: "CartoDB Light", url: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png", attribution: '© OpenStreetMap contributors © CARTO' }, cartoDark: { name: "CartoDB Dark", url: "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png", attribution: '© OpenStreetMap contributors © CARTO' }, stamen: { name: "Stamen Toner", url: "https://stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}{r}.png", attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap contributors' } } // Sample property data for Canadian cities const sampleProperties = [ { id: 1, coordinates: [49.2827, -123.1207] as [number, number], // Vancouver price: 1250000, type: "Detached", bedrooms: 4, bathrooms: 3, sqft: 2500, address: "1234 Maple Street, Vancouver, BC", status: "active" }, { id: 2, coordinates: [43.6532, -79.3832] as [number, number], // Toronto price: 890000, type: "Condo", bedrooms: 2, bathrooms: 2, sqft: 1200, address: "567 Bay Street, Toronto, ON", status: "active" }, { id: 3, coordinates: [51.0447, -114.0719] as [number, number], // Calgary price: 645000, type: "Townhouse", bedrooms: 3, bathrooms: 2.5, sqft: 1800, address: "890 Pine Road, Calgary, AB", status: "pending" }, { id: 4, coordinates: [52.1332, -106.3468] as [number, number], // Saskatoon price: 425000, type: "Detached", bedrooms: 3, bathrooms: 2, sqft: 1600, address: "456 Oak Avenue, Saskatoon, SK", status: "sold" } ] interface LeafletMapProps { onPropertySelect: (property: any) => void selectedProperty: any } export default function LeafletMap({ onPropertySelect, selectedProperty }: LeafletMapProps) { const mapRef = useRef(null) const mapContainerRef = useRef(null) const markersRef = useRef([]) const tileLayerRef = useRef(null) const [currentTileProvider, setCurrentTileProvider] = useState('carto') const formatCurrency = (value: number) => { return new Intl.NumberFormat('en-CA', { style: 'currency', currency: 'CAD', minimumFractionDigits: 0, maximumFractionDigits: 0, }).format(value) } const getMarkerColor = (status: string) => { switch (status) { case 'active': return '#10B981' // green case 'pending': return '#F59E0B' // orange case 'sold': return '#EF4444' // red default: return '#3B82F6' // blue } } const createCustomIcon = (property: any) => { const color = getMarkerColor(property.status) const priceText = formatCurrency(property.price).replace('CAD', '').trim() return L.divIcon({ html: `
${priceText}
`, className: 'custom-property-marker', iconSize: [120, 30], iconAnchor: [60, 30] }) } useEffect(() => { if (!mapContainerRef.current || mapRef.current) return // Initialize the map mapRef.current = L.map(mapContainerRef.current).setView([56.1304, -96.0000], 4) // Add selected tile provider const provider = tileProviders[currentTileProvider] tileLayerRef.current = L.tileLayer(provider.url, { attribution: provider.attribution, subdomains: 'abcd', maxZoom: 19 }).addTo(mapRef.current) // Add property markers sampleProperties.forEach(property => { const marker = L.marker(property.coordinates, { icon: createCustomIcon(property) }).addTo(mapRef.current!) marker.on('click', () => { onPropertySelect(property) // Fly to the clicked property mapRef.current?.setView(property.coordinates, 12, { animate: true }) }) markersRef.current.push(marker) }) // Cleanup function return () => { if (mapRef.current) { mapRef.current.remove() mapRef.current = null } markersRef.current = [] } }, [onPropertySelect, currentTileProvider]) // Handle tile provider changes useEffect(() => { if (!mapRef.current || !tileLayerRef.current) return // Remove current tile layer mapRef.current.removeLayer(tileLayerRef.current) // Add new tile layer const provider = tileProviders[currentTileProvider] tileLayerRef.current = L.tileLayer(provider.url, { attribution: provider.attribution, subdomains: 'abcd', maxZoom: 19 }).addTo(mapRef.current) }, [currentTileProvider]) // Update marker styles when selectedProperty changes useEffect(() => { markersRef.current.forEach((marker, index) => { const property = sampleProperties[index] const isSelected = selectedProperty?.id === property.id const icon = createCustomIcon(property) if (isSelected) { // Make selected marker larger and add pulse effect icon.options.html = icon.options.html?.replace( 'box-shadow: 0 2px 4px rgba(0,0,0,0.2);', 'box-shadow: 0 2px 4px rgba(0,0,0,0.2), 0 0 0 4px rgba(59, 130, 246, 0.3); transform: scale(1.1);' ) } marker.setIcon(icon) }) }, [selectedProperty]) const flyToProperty = (coordinates: [number, number]) => { if (mapRef.current) { mapRef.current.setView(coordinates, 12, { animate: true }) } } const resetView = () => { if (mapRef.current) { mapRef.current.setView([56.1304, -96.0000], 4, { animate: true }) } } return ( <>
{/* Map Style Selector */}
) }