1- import { MapContainer , TileLayer , CircleMarker , Tooltip } from "react-leaflet" ;
1+ import { MapContainer , TileLayer , CircleMarker , Tooltip , useMap } from "react-leaflet" ;
22import { useNavigate } from "react-router-dom" ;
33import type { WorldHeritageVm } from "../../../../domain/types.ts" ;
44import "leaflet/dist/leaflet.css" ;
5+ import { useEffect } from "react" ;
6+ import type { LatLngBoundsExpression } from "leaflet" ;
57
68type Props = {
79 items : WorldHeritageVm [ ] ;
@@ -18,6 +20,23 @@ const getColor = (category: string): string => CATEGORY_COLOR[category] ?? "#636
1820const isValidCoordinate = ( lat : number | null , lng : number | null ) : lat is number =>
1921 lat !== null && lng !== null && lat !== 0 && lng !== 0 ;
2022
23+ function FitBounds ( { items } : { items : WorldHeritageVm [ ] } ) {
24+ const map = useMap ( ) ;
25+
26+ useEffect ( ( ) => {
27+ if ( items . length === 0 ) return ;
28+
29+ const bounds : LatLngBoundsExpression = items . map ( ( item ) => [
30+ item . latitude as number ,
31+ item . longitude as number ,
32+ ] ) ;
33+
34+ map . fitBounds ( bounds , { padding : [ 40 , 40 ] } ) ;
35+ } , [ items , map ] ) ;
36+
37+ return null ;
38+ }
39+
2140export function SearchResultMapComponent ( { items } : Props ) {
2241 const navigate = useNavigate ( ) ;
2342
@@ -28,33 +47,36 @@ export function SearchResultMapComponent({ items }: Props) {
2847 }
2948
3049 return (
31- < MapContainer
32- center = { [ 20 , 0 ] }
33- zoom = { 2 }
34- style = { { height : "360px" , width : "100%" } }
35- scrollWheelZoom = { false }
36- >
37- < TileLayer url = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
38- { validItems . map ( ( item ) => (
39- < CircleMarker
40- key = { item . id }
41- center = { [ item . latitude as number , item . longitude as number ] }
42- radius = { 7 }
43- pathOptions = { {
44- color : getColor ( item . category ) ,
45- fillColor : getColor ( item . category ) ,
46- fillOpacity : 0.8 ,
47- } }
48- eventHandlers = { {
49- click : ( ) => navigate ( `/heritages/${ item . id } ` ) ,
50- } }
51- >
52- < Tooltip >
53- < div className = "text-xs font-semibold" > { item . name } </ div >
54- < div className = "text-xs text-zinc-500" > { item . category } </ div >
55- </ Tooltip >
56- </ CircleMarker >
57- ) ) }
58- </ MapContainer >
50+ < div className = { "my-8" } >
51+ < MapContainer
52+ center = { [ 20 , 0 ] }
53+ zoom = { 2 }
54+ style = { { height : "360px" , width : "100%" } }
55+ scrollWheelZoom = { false }
56+ >
57+ < TileLayer url = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
58+ < FitBounds items = { validItems } />
59+ { validItems . map ( ( item ) => (
60+ < CircleMarker
61+ key = { item . id }
62+ center = { [ item . latitude as number , item . longitude as number ] }
63+ radius = { 7 }
64+ pathOptions = { {
65+ color : getColor ( item . category ) ,
66+ fillColor : getColor ( item . category ) ,
67+ fillOpacity : 0.8 ,
68+ } }
69+ eventHandlers = { {
70+ click : ( ) => navigate ( `/heritages/${ item . id } ` ) ,
71+ } }
72+ >
73+ < Tooltip >
74+ < div className = "text-xs font-semibold" > { item . name } </ div >
75+ < div className = "text-xs text-zinc-500" > { item . category } </ div >
76+ </ Tooltip >
77+ </ CircleMarker >
78+ ) ) }
79+ </ MapContainer >
80+ </ div >
5981 ) ;
6082}
0 commit comments