Files
ATLAS/frontend/src/components/mapa/GeocercaLayer.tsx
FlotillasGPS Developer 51d78bacf4 FlotillasGPS - Sistema completo de monitoreo de flotillas GPS
Sistema completo para monitoreo y gestion de flotas de vehiculos con:
- Backend FastAPI con PostgreSQL/TimescaleDB
- Frontend React con TypeScript y TailwindCSS
- App movil React Native con Expo
- Soporte para dispositivos GPS, Meshtastic y celulares
- Video streaming en vivo con MediaMTX
- Geocercas, alertas, viajes y reportes
- Autenticacion JWT y WebSockets en tiempo real

Documentacion completa y guias de usuario incluidas.
2026-01-21 08:18:00 +00:00

113 lines
3.5 KiB
TypeScript

import { Circle, Polygon, Polyline, Popup, Tooltip } from 'react-leaflet'
import { Geocerca } from '@/types'
interface GeocercaLayerProps {
geocerca: Geocerca
editable?: boolean
onClick?: () => void
}
export default function GeocercaLayer({
geocerca,
editable = false,
onClick,
}: GeocercaLayerProps) {
const pathOptions = {
color: geocerca.color,
fillColor: geocerca.color,
fillOpacity: 0.2,
weight: 2,
}
const eventHandlers = {
click: () => onClick?.(),
}
// Circle geocerca
if (geocerca.tipo === 'circulo' && geocerca.centroLat && geocerca.centroLng && geocerca.radio) {
return (
<Circle
center={[geocerca.centroLat, geocerca.centroLng]}
radius={geocerca.radio}
pathOptions={pathOptions}
eventHandlers={eventHandlers}
>
<Tooltip permanent={false} direction="top">
<span className="text-sm font-medium">{geocerca.nombre}</span>
</Tooltip>
<Popup>
<GeocercaPopup geocerca={geocerca} />
</Popup>
</Circle>
)
}
// Polygon geocerca
if (geocerca.tipo === 'poligono' && geocerca.vertices && geocerca.vertices.length > 2) {
const positions = geocerca.vertices.map((v) => [v.lat, v.lng] as [number, number])
return (
<Polygon positions={positions} pathOptions={pathOptions} eventHandlers={eventHandlers}>
<Tooltip permanent={false} direction="top">
<span className="text-sm font-medium">{geocerca.nombre}</span>
</Tooltip>
<Popup>
<GeocercaPopup geocerca={geocerca} />
</Popup>
</Polygon>
)
}
// Route geocerca
if (geocerca.tipo === 'ruta' && geocerca.vertices && geocerca.vertices.length > 1) {
const positions = geocerca.vertices.map((v) => [v.lat, v.lng] as [number, number])
return (
<Polyline positions={positions} pathOptions={{ ...pathOptions, fillOpacity: 0 }} eventHandlers={eventHandlers}>
<Tooltip permanent={false} direction="top">
<span className="text-sm font-medium">{geocerca.nombre}</span>
</Tooltip>
<Popup>
<GeocercaPopup geocerca={geocerca} />
</Popup>
</Polyline>
)
}
return null
}
// Popup content
function GeocercaPopup({ geocerca }: { geocerca: Geocerca }) {
return (
<div className="p-1">
<h3 className="text-sm font-semibold text-white mb-1">{geocerca.nombre}</h3>
{geocerca.descripcion && (
<p className="text-xs text-slate-400 mb-2">{geocerca.descripcion}</p>
)}
<div className="space-y-1 text-xs">
<div className="flex justify-between">
<span className="text-slate-500">Tipo:</span>
<span className="text-slate-300 capitalize">{geocerca.tipo}</span>
</div>
<div className="flex justify-between">
<span className="text-slate-500">Accion:</span>
<span className="text-slate-300 capitalize">{geocerca.accion}</span>
</div>
{geocerca.velocidadMaxima && (
<div className="flex justify-between">
<span className="text-slate-500">Vel. max:</span>
<span className="text-slate-300">{geocerca.velocidadMaxima} km/h</span>
</div>
)}
{geocerca.tipo === 'circulo' && geocerca.radio && (
<div className="flex justify-between">
<span className="text-slate-500">Radio:</span>
<span className="text-slate-300">{geocerca.radio} m</span>
</div>
)}
</div>
</div>
)
}