Files
MOPC-Portal/src/components/charts/leaflet-map.tsx
Matt a606292aaa Initial commit: MOPC platform with Docker deployment setup
Full Next.js 15 platform with tRPC, Prisma, PostgreSQL, NextAuth.
Includes production Dockerfile (multi-stage, port 7600), docker-compose
with registry-based image pull, Gitea Actions CI workflow, nginx config
for portal.monaco-opc.com, deployment scripts, and DEPLOYMENT.md guide.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 13:41:32 +01:00

79 lines
2.1 KiB
TypeScript

'use client'
import { useMemo } from 'react'
import { MapContainer, TileLayer, CircleMarker, Tooltip } from 'react-leaflet'
import 'leaflet/dist/leaflet.css'
import { COUNTRIES } from '@/lib/countries'
type CountryData = { countryCode: string; count: number }
type LeafletMapProps = {
data: CountryData[]
compact?: boolean
}
export default function LeafletMap({ data, compact }: LeafletMapProps) {
const markers = useMemo(() => {
const maxCount = Math.max(...data.map((d) => d.count), 1)
return data
.filter((d) => d.countryCode !== 'UNKNOWN' && COUNTRIES[d.countryCode])
.map((d) => {
const country = COUNTRIES[d.countryCode]
const ratio = d.count / maxCount
const radius = 5 + ratio * 15
return {
code: d.countryCode,
name: country.name,
position: [country.lat, country.lng] as [number, number],
count: d.count,
radius,
ratio,
}
})
}, [data])
return (
<MapContainer
center={[20, 0]}
zoom={compact ? 1 : 2}
scrollWheelZoom
zoomControl
dragging
doubleClickZoom
style={{
height: compact ? 400 : 500,
width: '100%',
borderRadius: '0.5rem',
background: '#f0f0f0',
}}
attributionControl={false}
>
<TileLayer
url="https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png"
/>
{markers.map((marker) => (
<CircleMarker
key={marker.code}
center={marker.position}
radius={marker.radius}
pathOptions={{
color: '#de0f1e',
fillColor: '#de0f1e',
fillOpacity: 0.35 + marker.ratio * 0.45,
weight: 1.5,
}}
>
<Tooltip direction="top" offset={[0, -marker.radius]}>
<div className="text-xs font-medium">
<span className="font-semibold">{marker.name}</span>
<br />
{marker.count} project{marker.count !== 1 ? 's' : ''}
</div>
</Tooltip>
</CircleMarker>
))}
</MapContainer>
)
}