From 811bde1e64ecfd2df45a98af03527afdaa343212 Mon Sep 17 00:00:00 2001 From: patrickwebsdev Date: Fri, 8 Nov 2024 15:34:52 -0300 Subject: [PATCH] feat: added api for request and offers --- .env.example | 1 + src/app/api/mapa/route.ts | 44 ++++++++++++ src/app/api/ofertas/route.ts | 52 ++++++++++---- src/app/api/solicitudes/[id]/route.ts | 27 +++++++ src/app/api/solicitudes/route.ts | 84 +++++++++++----------- src/app/casos-activos/mapa/page.tsx | 49 +++++-------- src/app/casos-activos/ofertas/page.tsx | 23 +++--- src/app/casos-activos/solicitudes/page.tsx | 4 +- src/components/OfferCard.tsx | 11 ++- src/components/SolicitudCardMap.tsx | 55 ++++++++++++++ src/components/map/map.tsx | 2 - 11 files changed, 249 insertions(+), 103 deletions(-) create mode 100644 src/app/api/mapa/route.ts create mode 100644 src/app/api/solicitudes/[id]/route.ts create mode 100644 src/components/SolicitudCardMap.tsx diff --git a/.env.example b/.env.example index 1ad7baa7..56db3dea 100644 --- a/.env.example +++ b/.env.example @@ -2,6 +2,7 @@ NEXT_PUBLIC_BASE_URL=https://ajudadana.es NEXT_PUBLIC_NODE_ENV=production NEXT_PUBLIC_SUPABASE_URL= NEXT_PUBLIC_SUPABASE_ANON_KEY= +SUPABASE_SERVICE_ROLE= SUPABASE_GOOGLE_AUTH_ID= SUPABASE_GOOGLE_AUTH_SECRET= API_KEY= \ No newline at end of file diff --git a/src/app/api/mapa/route.ts b/src/app/api/mapa/route.ts new file mode 100644 index 00000000..81ec4e10 --- /dev/null +++ b/src/app/api/mapa/route.ts @@ -0,0 +1,44 @@ +import { NextRequest } from 'next/server'; +import { createServerRoleClient } from '@/lib/supabase/server_role'; + +export async function GET(req: NextRequest) { + const url = new URL(req.url); + const searchParams: any = url.searchParams; + + const help_type = searchParams.get('type') || null; + const urgency = searchParams.get('urgency') || null; + const acepta = searchParams.get('acepta') || null; + + const supabase = await createServerRoleClient(); + // const { data: dataUser, error: errorUser } = await supabase.auth.getUser(); + // if (errorUser || !dataUser?.user) { + // return Response.json({ message: 'Not logged.', errorUser }); + // } + + const query = supabase + .from('help_requests') + .select('id, user_id, latitude, longitude, urgency') + .eq('type', 'necesita'); + + if (help_type !== null) { + query.contains('help_type', [help_type]); + } + if (urgency !== null) { + query.eq('urgency', urgency); + } + + query.neq('status', 'finished'); + + const { data, error } = await query.order('created_at', { ascending: false }); + + if (acepta !== 'todos') { + query.contains('accepted_items', [acepta]); + } + + if (error) { + return Response.json({ error }); + } else { + return Response.json({ data }); + } + return Response.json({ message: 'Error' }); +} diff --git a/src/app/api/ofertas/route.ts b/src/app/api/ofertas/route.ts index 3c9b7251..8f3c60dc 100644 --- a/src/app/api/ofertas/route.ts +++ b/src/app/api/ofertas/route.ts @@ -1,16 +1,42 @@ -import { createClient } from '@/lib/supabase/server'; +import { NextRequest } from 'next/server'; +import { createServerRoleClient } from '@/lib/supabase/server_role'; -export async function GET() { - const supabase = await createClient(); - const { data, error } = await supabase.auth.getUser(); - if (error || !data?.user) { - return Response.json({ message: 'Not logged.', error }); - } - const email = data.user.email; - const registeredPost = await supabase +export async function GET(req: NextRequest) { + // Acceder a los parámetros de búsqueda + const url = new URL(req.url); + const searchParams: any = url.searchParams; + + const help_type = searchParams.get('type'); + const currentPage = searchParams.get('page') ?? 1; + const itemsPerPage = 10; + + const supabase = await createServerRoleClient(); + // const { data: dataUser, error: errorUser } = await supabase.auth.getUser(); + // if (errorUser || !dataUser?.user) { + // return Response.json({ message: 'Not logged.', errorUser }); + // } + + const query = supabase .from('help_requests') - .select('id') - .eq('type', 'ofrece') - .or(`contact_info.ilike.%${email}%,additional_info.cs.${JSON.stringify({ email: email })}`); - return Response.json({ registeredPost }); + .select( + 'id, created_at,name,location,description,contact_info,additional_info->experience,status,resources,help_type,town_id,other_help', + { count: 'exact' }, + ) + .eq('type', 'ofrece'); + + if (help_type !== null) { + query.contains('help_type', [help_type]); + } + + query.neq('status', 'finished'); + + const { data, count, error } = await query + .range((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage - 1) + .order('created_at', { ascending: false }); + + if (error) { + return Response.json({ error }); + } + const countResponse = count ?? 0; + return Response.json({ data, count: countResponse }); } diff --git a/src/app/api/solicitudes/[id]/route.ts b/src/app/api/solicitudes/[id]/route.ts new file mode 100644 index 00000000..037cb5ef --- /dev/null +++ b/src/app/api/solicitudes/[id]/route.ts @@ -0,0 +1,27 @@ +import { createServerRoleClient } from '@/lib/supabase/server_role'; +import { NextRequest } from 'next/server'; + +export async function GET(request: NextRequest, { params }: { params: { id: string } }) { + const id = params.id; + + const supabase = await createServerRoleClient(); + // const { data: dataUser, error: errorUser } = await supabase.auth.getUser(); + // if (errorUser || !dataUser?.user) { + // return Response.json({ message: 'Not logged.', errorUser }); + // } + + const { data, error } = await supabase + .from('help_requests') + .select( + 'id, created_at, name, location, description, urgency, number_of_people, contact_info, additional_info->special_situations, status, resources, latitude, longitude, coordinates, help_type, people_needed, other_help,town_id', + { count: 'exact' }, + ) + .eq('id', id) + .limit(1) + .select(); + + if (error) { + return Response.json({ error }); + } + return Response.json({ data }); +} diff --git a/src/app/api/solicitudes/route.ts b/src/app/api/solicitudes/route.ts index 9946c292..92b759d3 100644 --- a/src/app/api/solicitudes/route.ts +++ b/src/app/api/solicitudes/route.ts @@ -1,48 +1,52 @@ import { NextRequest } from 'next/server'; import { createServerRoleClient } from '@/lib/supabase/server_role'; - export async function GET(req: NextRequest) { - // Acceder a los parámetros de búsqueda - const url = new URL(req.url); - const searchParams: any = url.searchParams; - - const help_type = searchParams.get('type'); - const town_id = searchParams.get('town'); - const urgency = searchParams.get('urgency'); - const currentPage = searchParams.get('page') ?? 1 ; - const itemsPerPage = 10; - - const supabase = await createServerRoleClient(); +export async function GET(req: NextRequest) { + // Acceder a los parámetros de búsqueda + const url = new URL(req.url); + const searchParams: any = url.searchParams; + + const help_type = searchParams.get('type') || null; + const town_id = searchParams.get('town') || null; + const urgency = searchParams.get('urgency') || null; + const currentPage = searchParams.get('page') ?? 1; + const itemsPerPage = 10; + + const supabase = await createServerRoleClient(); // const { data: dataUser, error: errorUser } = await supabase.auth.getUser(); // if (errorUser || !dataUser?.user) { // return Response.json({ message: 'Not logged.', errorUser }); // } - const query = supabase.from('help_requests').select('id, created_at, name, location, description, urgency, number_of_people, contact_info, additional_info->special_situations, status, resources, help_type, people_needed, other_help', { count: 'exact' }).eq('type', 'necesita'); - - if (help_type !== null) { - query.contains('help_type', [help_type]); - } - - if (town_id !== null) { - query.eq('town_id', town_id); - } - - if (urgency !== null) { - query.eq('urgency', urgency); - } - - query.neq('status', 'finished'); - - const { data, count, error } = await query - .range((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage - 1) - .order('created_at', { ascending: false }); - - if (error) { - return Response.json({error}) - } else { - const countResponse = count ?? 0; - return Response.json({data, count: countResponse }); - } - return Response.json({message: 'Error'}); -} \ No newline at end of file + const query = supabase + .from('help_requests') + .select( + 'id, created_at, name, location, description, urgency, number_of_people, contact_info, additional_info->special_situations, status, resources, latitude, longitude, coordinates, help_type, people_needed, other_help,town_id', + { count: 'exact' }, + ) + .eq('type', 'necesita'); + + if (help_type !== null) { + query.contains('help_type', [help_type]); + } + + if (town_id !== null) { + query.eq('town_id', town_id); + } + + if (urgency !== null) { + query.eq('urgency', urgency); + } + + query.neq('status', 'finished'); + + const { data, count, error } = await query + .range((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage - 1) + .order('created_at', { ascending: false }); + + if (error) { + return Response.json({ error }); + } + const countResponse = count ?? 0; + return Response.json({ data, count: countResponse }); +} diff --git a/src/app/casos-activos/mapa/page.tsx b/src/app/casos-activos/mapa/page.tsx index 23822f74..c982913d 100644 --- a/src/app/casos-activos/mapa/page.tsx +++ b/src/app/casos-activos/mapa/page.tsx @@ -1,14 +1,11 @@ 'use client'; import { useState, useEffect, Suspense } from 'react'; -import { supabase } from '@/lib/supabase/client'; -import SolicitudCard from '@/components/SolicitudCard'; import { useRouter, useSearchParams } from 'next/navigation'; import { tiposAyudaOptions } from '@/helpers/constants'; import Map, { PinMapa } from '@/components/map/map'; import PickupPoint from '@/components/PickupPoint'; - -export const dynamic = 'force-dynamic'; +import SolicitudCardMap from '@/components/SolicitudCardMap'; export default function MapaPage() { return ( @@ -55,7 +52,7 @@ function Mapa() { latitude: request.latitude ?? 0, longitude: request.longitude ?? 0, id: request.id, - popup: , + popup: , }; } @@ -70,44 +67,34 @@ function Mapa() { } async function fetchData() { + const url = process.env.NEXT_PUBLIC_BASE_URL + '/api/mapa/?'; try { setLoading(true); setError(null); + const filter = []; - // Comenzamos la consulta - const query = supabase.from('help_requests').select('*').eq('type', 'necesita'); if (filtroData.tipoAyuda !== 'todas') { - query.contains('help_type', [filtroData.tipoAyuda]); + filter.push('type=' + filtroData.tipoAyuda); + } + if (filtroData.pueblo !== 'todos') { + filter.push('town=' + filtroData.pueblo); } if (filtroData.urgencia !== 'todas') { - query.eq('urgency', filtroData.urgencia); + filter.push('urgency=' + filtroData.urgencia); } - - query.neq('status', 'finished'); - - 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]); + if (filtroData.acepta !== 'todas') { + filter.push('acepta=' + filtroData.acepta); } - - const { data: pickupData, error: pickupError } = await pickupQuery.order('created_at', { ascending: false }); - - let allData = []; - if (error) { - console.log('Error fetching solicitudes:', error); + const filterUrl = url + filter.join('&'); + const response = await fetch(filterUrl); + if (!response.ok) { + console.log(`Error fetching solicitudes: ${response.status}`); + setData([]); } else { + const { data, count } = await response.json(); const markers = data.map(transformHelpRequestToMarker); - allData.push(...(markers || [])); - } - if (pickupError) { - console.log('Error fetching pickup points:', pickupError); - } else { - const pickupMarkers = pickupData.map(transformPickupRequestToMarker); - allData.push(...(pickupMarkers || [])); + setData(markers || []); } - setData(allData); } catch (err) { console.log('Error general:', err); setError('Error de conexión.'); diff --git a/src/app/casos-activos/ofertas/page.tsx b/src/app/casos-activos/ofertas/page.tsx index d1b8f5de..3fcdd54e 100644 --- a/src/app/casos-activos/ofertas/page.tsx +++ b/src/app/casos-activos/ofertas/page.tsx @@ -60,28 +60,23 @@ function Ofertas() { useEffect(() => { async function fetchData() { + const url = process.env.NEXT_PUBLIC_BASE_URL + '/api/ofertas/?'; try { setLoading(true); setError(null); + const filter = []; - // Comenzamos la consulta - const query = supabase.from('help_requests').select('*', { count: 'exact' }).eq('type', 'ofrece'); - - // Solo agregar filtro si no es "todos" if (filtroData.ayuda !== 'todas') { - query.contains('help_type', [filtroData.ayuda]); + filter.push('type=' + filtroData.ayuda); } - - query.neq('status', 'finished'); - // Ejecutar la consulta con paginación - const { data, count, error } = await query - .range((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage - 1) - .order('created_at', { ascending: false }); - - if (error) { - console.log('Error fetching solicitudes:', error); + filter.push('page=' + currentPage); + const filterUrl = url + filter.join('&'); + const response = await fetch(filterUrl); + if (!response.ok) { + console.log(`Error fetching solicitudes: ${response.status}`); setData([]); } else { + const { data, count } = await response.json(); setData(data || []); setCurrentCount(count ?? 0); } diff --git a/src/app/casos-activos/solicitudes/page.tsx b/src/app/casos-activos/solicitudes/page.tsx index 5a161806..e2c9a82f 100644 --- a/src/app/casos-activos/solicitudes/page.tsx +++ b/src/app/casos-activos/solicitudes/page.tsx @@ -70,12 +70,12 @@ function Solicitudes() { const filter = []; if (filtroData.tipoAyuda !== 'todas') { - filter.push('helptype=' + filtroData.tipoAyuda); + filter.push('type=' + filtroData.tipoAyuda); } // Solo agregar filtro si no es "todos" if (filtroData.pueblo !== 'todos') { - filter.push('town_id=' + filtroData.pueblo); + filter.push('town=' + filtroData.pueblo); } // Solo agregar filtro si no es "todas" diff --git a/src/components/OfferCard.tsx b/src/components/OfferCard.tsx index 4f4ab612..8b7eaf68 100644 --- a/src/components/OfferCard.tsx +++ b/src/components/OfferCard.tsx @@ -5,7 +5,7 @@ import { HelpRequestData } from '@/types/Requests'; import { useTowns } from '@/context/TownProvider'; type OfferCardProps = { - caso: HelpRequestData; + caso: HelpRequestData & { experience?: string }; showLink?: boolean; }; export default function OfferCard({ caso, showLink = true }: OfferCardProps) { @@ -98,6 +98,15 @@ export default function OfferCard({ caso, showLink = true }: OfferCardProps) { )} + {caso.experience && ( +
+ + + Experiencia: + {' ' + caso.experience} + +
+ )}
diff --git a/src/components/SolicitudCardMap.tsx b/src/components/SolicitudCardMap.tsx new file mode 100644 index 00000000..40a315bb --- /dev/null +++ b/src/components/SolicitudCardMap.tsx @@ -0,0 +1,55 @@ +import React, { useEffect, useState } from 'react'; +import SolicitudCard from './SolicitudCard'; + +interface SolicitudCardMapProps { + id: { + caso: string; + }; +} + +export default function SolicitudCardMap({ id }: SolicitudCardMapProps) { + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [caso, setCaso] = useState(null); + + useEffect(() => { + async function getRequest() { + const url = `${process.env.NEXT_PUBLIC_BASE_URL}/api/solicitudes/${id}`; + try { + const response = await fetch(url); + if (!response.ok) { + console.log(`Error fetching solicitudes: ${response.status}`); + setError('Error fetching data'); + return; + } + + const { data } = await response.json(); + console.log(data); + setCaso(data[0]); + setLoading(false); + } catch (err) { + console.log('Error general:', err); + setError('Error: ' + err); + } + } + getRequest(); + }, [id]); + + if (loading) { + return ( +
+
+
+ ); + } + + if (error) { + return ( +
+

{error}

+
+ ); + } + + return ; +} diff --git a/src/components/map/map.tsx b/src/components/map/map.tsx index dd115b84..6130b1f9 100644 --- a/src/components/map/map.tsx +++ b/src/components/map/map.tsx @@ -36,8 +36,6 @@ const Map: FC = ({ markers = [] }) => { const [selectedMarker, setSelectedMarker] = useState(null); const { toggleModal } = useModal(); - - console.log(selectedMarker); return (