diff --git a/src/app/casos-activos/mapa/page.js b/src/app/casos-activos/mapa/page.js index 49ea4b60..ac40b7ce 100644 --- a/src/app/casos-activos/mapa/page.js +++ b/src/app/casos-activos/mapa/page.js @@ -7,15 +7,14 @@ import { useRouter, useSearchParams } from 'next/navigation'; import { tiposAyudaOptions } from '@/helpers/constants'; import Map from '@/components/map/map'; import ReactDOMServer from 'react-dom/server'; -import { useTowns } from '../../../context/TownProvider'; -import { useSession } from '../../../context/SessionProvider'; +import PickupPoint from '@/components/PickupPoint'; +import { useTowns } from '@/context/TownProvider'; const PAIPORTA_LAT_LNG = [-0.41667, 39.42333]; const DEFAULT_ZOOM = 12; export default function Mapa() { const towns = useTowns(); - const session = useSession(); const searchParams = useSearchParams(); const router = useRouter(); @@ -34,6 +33,7 @@ export default function Mapa() { urgencia: searchParams.get('urgencia') || 'todas', tipoAyuda: searchParams.get('tipoAyuda') || 'todas', pueblo: searchParams.get('pueblo') || 'todos', + acepta: searchParams.get('acepta') || 'todos', }); const changeDataFilter = (type, newFilter) => { @@ -56,11 +56,15 @@ export default function Mapa() { }; } - // caso, - // towns, - // isHref, - // button = { text: 'Ver solicitud', link: '/solicitud/' }, - // isEdit = false, + function transformPickupRequestToMarker(point) { + return { + urgency: point.urgency || 'baja', + coordinates: [point.longitude ?? 0, point.latitude ?? 0], + width: '600px', + descriptionHTML: ReactDOMServer.renderToString(), + }; + } + async function fetchData() { try { setLoading(true); @@ -68,24 +72,37 @@ export default function Mapa() { // Comenzamos la consulta const query = supabase.from('help_requests').select('*').eq('type', 'necesita'); - if (filtroData.tipoAyuda !== 'todas') { query.contains('help_type', [filtroData.tipoAyuda]); } - if (filtroData.urgencia !== 'todas') { query.eq('urgency', filtroData.urgencia); } const { data, error } = await query.order('created_at', { ascending: false }); + const pickupQuery = supabase.from('collection_points').select('*', { count: 'exact' }); + if (filtroData.acepta !== 'todos') { + query.contains('accepted_items', [filtroData.acepta]); + } + + const { data: pickupData, error: pickupError } = await pickupQuery.order('created_at', { ascending: false }); + + let allData = []; if (error) { console.log('Error fetching solicitudes:', error); - setData([]); } else { const markers = data.map(transformHelpRequestToMarker); - setData(markers || []); + allData.push(...(markers || [])); } + if (pickupError) { + console.log('Error fetching pickup points:', pickupError); + } else { + const pickupMarkers = pickupData.map(transformPickupRequestToMarker); + allData.push(...(pickupMarkers || [])); + } + + setData(allData); } catch (err) { console.log('Error general:', err); setError('Error de conexión.'); @@ -143,6 +160,7 @@ export default function Mapa() { +
diff --git a/src/app/casos-activos/puntos/page.js b/src/app/casos-activos/puntos/page.js index 06c5c2ad..1e99ab76 100644 --- a/src/app/casos-activos/puntos/page.js +++ b/src/app/casos-activos/puntos/page.js @@ -6,7 +6,8 @@ import { supabase } from '@/lib/supabase/client'; import { tiposAyudaAcepta } from '@/helpers/constants'; import Pagination from '@/components/Pagination'; import { useRouter, useSearchParams } from 'next/navigation'; -import { useTowns } from '../../../context/TownProvider'; +import PickupPoint from '@/components/PickupPoint'; +import { useTowns } from '@/context/TownProvider'; export default function Puntos() { const towns = useTowns(); @@ -138,77 +139,7 @@ export default function Puntos() { ) : ( - data.map((punto) => ( -
-
-
-

{punto.name}

-
- - - {punto.location} - -
-
-
- - Referencia: {punto.id} - - - {punto.status === 'active' ? 'Activo' : 'Inactivo'} - -
-
-
-
- Ciudad: {punto.city} -
- {punto.contact_name && ( -
- Responsable: {punto.contact_name} -
- )} - {punto.contact_phone && ( -
- Teléfono: {punto.contact_phone} -
- )} - {punto.accepted_items && ( -
- Acepta:{' '} - {Array.isArray(punto.accepted_items) ? punto.accepted_items.join(', ') : punto.accepted_items} -
- )} - {punto.urgent_needs && ( -
- Necesidades urgentes: -

{punto.urgent_needs}

-
- )} - {punto.schedule && ( -
- Horario: -

{punto.schedule}

-
- )} - {punto.additional_info && ( -
- Información adicional: -

- {typeof punto.additional_info === 'string' - ? punto.additional_info - : JSON.stringify(punto.additional_info)} -

-
- )} -
-
- )) + data.map((punto) => ) )}
diff --git a/src/components/PickupPoint.js b/src/components/PickupPoint.js new file mode 100644 index 00000000..c0f6f95b --- /dev/null +++ b/src/components/PickupPoint.js @@ -0,0 +1,77 @@ +import { MapPin } from 'lucide-react'; + +const PickupPoint = ({ point }) => { + return ( +
+
+
+

{point.name}

+ +
+
+ + Referencia: {point.id} + + + {point.status === 'active' ? 'Activo' : 'Inactivo'} + +
+
+
+
+ Ciudad: {point.city} +
+ {point.contact_name && ( +
+ Responsable: {point.contact_name} +
+ )} + {point.contact_phone && ( +
+ Teléfono: {point.contact_phone} +
+ )} + {point.accepted_items && ( +
+ Acepta:{' '} + {Array.isArray(point.accepted_items) ? point.accepted_items.join(', ') : point.accepted_items} +
+ )} + {point.urgent_needs && ( +
+ Necesidades urgentes: +

{point.urgent_needs}

+
+ )} + {point.schedule && ( +
+ Horario: +

{point.schedule}

+
+ )} + {point.additional_info && ( +
+ Información adicional: +

+ {typeof point.additional_info === 'string' + ? point.additional_info + : JSON.stringify(point.additional_info)} +

+
+ )} +
+
+ ); +}; + +export default PickupPoint; diff --git a/src/components/map/map.js b/src/components/map/map.js deleted file mode 100644 index 754e2ee9..00000000 --- a/src/components/map/map.js +++ /dev/null @@ -1,53 +0,0 @@ -import { useEffect, useRef } from 'react'; -import maplibregl from 'maplibre-gl'; -import 'maplibre-gl/dist/maplibre-gl.css'; - -const urgencyToColor = { - alta: '#ef4444', //text-red-500 - media: '#f59e0b', //text-amber-500 - baja: '#10b981', //text-emerald-500 -}; - -export default function Map({ center = [0, 0], zoom = 2, markers = [] }) { - const mapContainerRef = useRef(null); - const mapRef = useRef(null); - - useEffect(() => { - if (!mapRef.current) { - mapRef.current = new maplibregl.Map({ - container: mapContainerRef.current, - style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json', - center: center, - zoom: zoom, - }); - - mapRef.current.addControl(new maplibregl.NavigationControl(), 'top-right'); - } - - mapRef.current.markers?.forEach((marker) => marker.remove()); - mapRef.current.markers = []; - - markers.forEach((markerData) => { - new maplibregl.Marker({ - color: urgencyToColor[markerData.urgency], - }) - .setLngLat(markerData.coordinates) - .setPopup( - new maplibregl.Popup({ - className: 'map-popup', - maxWidth: markerData.width, - anchor: 'left', - }).setHTML(markerData.descriptionHTML), - ) - - .addTo(mapRef.current); - }); - - return () => { - mapRef.current?.remove(); - mapRef.current = null; - }; - }, [center, zoom, markers]); - - return
; -} diff --git a/src/components/map/map.tsx b/src/components/map/map.tsx new file mode 100644 index 00000000..f93ec317 --- /dev/null +++ b/src/components/map/map.tsx @@ -0,0 +1,74 @@ +import { FC, useEffect, useRef } from 'react'; +import maplibregl from 'maplibre-gl'; +import 'maplibre-gl/dist/maplibre-gl.css'; + +const urgencyToColor = { + alta: '#ef4444', //text-red-500 + media: '#f59e0b', //text-amber-500 + baja: '#10b981', //text-emerald-500 +}; + +type MapProps = { + center?: [number, number]; + zoom?: number; + markers?: { + coordinates: [number, number]; + urgency: 'alta' | 'media' | 'baja'; + descriptionHTML: string; + width: number; + }[]; +}; + +const Map: FC = ({ center = [0, 0], zoom = 2, markers = [] }) => { + const mapContainerRef = useRef(null); + const mapRef = useRef(null); + const markerRefs = useRef([]); + + useEffect(() => { + if (!mapRef.current) { + mapRef.current = new maplibregl.Map({ + container: mapContainerRef.current!, + style: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json', + center: center, + zoom: zoom, + }); + mapRef.current.addControl(new maplibregl.NavigationControl(), 'top-right'); + } else { + // Update center and zoom when props change + mapRef.current.setCenter(center); + mapRef.current.setZoom(zoom); + } + + // Clear existing markers + markerRefs.current.forEach((marker) => marker.remove()); + markerRefs.current = []; + + // Add new markers + markers.forEach((markerData) => { + const marker = new maplibregl.Marker({ + color: urgencyToColor[markerData.urgency], + }) + .setLngLat(markerData.coordinates) + .setPopup( + new maplibregl.Popup({ + className: 'map-popup', + maxWidth: `${markerData.width}px`, + anchor: 'left', + }).setHTML(markerData.descriptionHTML) + ) + .addTo(mapRef.current!); + + markerRefs.current.push(marker); + }); + + // Clean up function to remove markers only + return () => { + markerRefs.current.forEach((marker) => marker.remove()); + markerRefs.current = []; + }; + }, [center, zoom, markers]); + + return
; +}; + +export default Map;